diff --git a/README-zh.md b/README-zh.md index 4d513ad..4cf45fb 100644 --- a/README-zh.md +++ b/README-zh.md @@ -1,3 +1,5 @@ +*本仓库没有包含任何第三方库和kxver模块的源码或库文件,kxver模块主要是用于版本控制,特别是与旗舰版的相关的功能如数据加密,它是团队的唯一资金来源,也是产品健康维护和升级的重要保证,在没有解决资金来源之前,并不计划开放该模块。* +***

WoTerm - Another Remote Access Assistant

跨平台/小内存/多协议/多功能/云同步

diff --git a/README.md b/README.md index 24e713a..cc603ab 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +*This repository does not contain any third-party libraries or source code for the kxver module. The kxver module is primarily used for version control, particularly for features related to the ultimate version such as data encryption. It is the team's sole source of funding and an important guarantee for the health maintenance and upgrade of the product.Until the funding source is resolved, there are no plans to open the source code for this module.* +***

WoTerm - Another Remote Access Assistant

Cross platform / small memory / multi-protocol / multi-function / cloud sync

diff --git a/kxterm/qkxscreen.h b/kxterm/qkxscreen.h index 2953f4f..84a18d3 100644 --- a/kxterm/qkxscreen.h +++ b/kxterm/qkxscreen.h @@ -41,7 +41,7 @@ class QKxScreen : public QObject void clearScreen(); void resize(int rows, int cols); inline int rows() { return m_rows; } - inline int columens() { return m_columns; } + inline int columns() { return m_columns; } TermLine lineAt(int y) const; TermCursor cursor() const; bool visibleCursor() const; diff --git a/kxterm/qkxview.cpp b/kxterm/qkxview.cpp index bee6622..e43af52 100644 --- a/kxterm/qkxview.cpp +++ b/kxterm/qkxview.cpp @@ -125,7 +125,7 @@ void QKxView::setSelection(const QMap &sels) void QKxView::selectWord(const QPoint& pt) { - int cols = m_screen->columens(); + int cols = m_screen->columns(); int x = pt.x(); int y = pt.y(); const TermLine& line = lineAt(pt.y()); @@ -166,7 +166,7 @@ void QKxView::selectWord(const QPoint& pt) void QKxView::selectLine(int y) { int rows = lineCount(); - int cols = m_screen->columens(); + int cols = m_screen->columns(); const TermLine& line = lineAt(y); if(line.cs.isEmpty()) { setSelection(QPoint(0, y), QPoint(cols, y)); @@ -331,7 +331,7 @@ QList QKxView::selectedLines() bool QKxView::find(const QString &key, bool match, bool regular) { QList pos; - pos.reserve(m_screen->columens()); + pos.reserve(m_screen->columns()); m_findText = key; m_findLength = 0; if(key.isEmpty()) { @@ -360,6 +360,21 @@ bool QKxView::find(const QString &key, bool match, bool regular) QPoint pt2 = pos.at(cnt - 1 + idx); m_findKey = intFromPoint(pt1); m_findLength = cnt; + if(pt1.y() != pt2.y()) { + QMap sels; + for(int i = idx; i <= cnt-1+idx; i++) { + QPoint pt = pos.at(i); + if(pt1.y() != pt.y()) { + sels.insert(pt1, pt2); + pt1 = pt2 = pt; + }else{ + pt2 = pt; + } + } + sels.insert(pt1, pt2); + setSelection(sels); + return true; + } setSelection(pt1, pt2); return true; } @@ -375,7 +390,7 @@ bool QKxView::find(const QString &key, bool match, bool regular) bool QKxView::findPrev(bool match, bool regular) { QList pos; - pos.reserve(m_screen->columens()); + pos.reserve(m_screen->columns()); if(m_findText.isEmpty()) { return true; } @@ -402,6 +417,21 @@ bool QKxView::findPrev(bool match, bool regular) QPoint pt2 = pos.at(cnt - 1 + idx); m_findKey = intFromPoint(pt1); m_findLength = cnt; + if(pt1.y() != pt2.y()) { + QMap sels; + for(int i = idx; i <= cnt-1+idx; i++) { + QPoint pt = pos.at(i); + if(pt1.y() != pt.y()) { + sels.insert(pt1, pt2); + pt1 = pt2 = pt; + }else{ + pt2 = pt; + } + } + sels.insert(pt1, pt2); + setSelection(sels); + return true; + } setSelection(pt1, pt2); return true; } @@ -417,7 +447,7 @@ bool QKxView::findPrev(bool match, bool regular) bool QKxView::findNext(bool match, bool regular) { QList pos; - pos.reserve(m_screen->columens()); + pos.reserve(m_screen->columns()); if(m_findText.isEmpty()) { return true; } @@ -444,6 +474,21 @@ bool QKxView::findNext(bool match, bool regular) QPoint pt2 = pos.at(cnt - 1 + idx); m_findKey = intFromPoint(pt1); m_findLength = cnt; + if(pt1.y() != pt2.y()) { + QMap sels; + for(int i = idx; i <= cnt-1+idx; i++) { + QPoint pt = pos.at(i); + if(pt1.y() != pt.y()) { + sels.insert(pt1, pt2); + pt1 = pt2 = pt; + }else{ + pt2 = pt; + } + } + sels.insert(pt1, pt2); + setSelection(sels); + return true; + } setSelection(pt1, pt2); return true; } @@ -458,7 +503,7 @@ bool QKxView::findNext(bool match, bool regular) void QKxView::findAll(bool match, bool regular) { QList pos; - pos.reserve(m_screen->columens()); + pos.reserve(m_screen->columns()); clearSelection(); if(m_findText.isEmpty()) { return; @@ -478,7 +523,22 @@ void QKxView::findAll(bool match, bool regular) const QStringList& caps = rgx.capturedTexts(); for(int i = 0; i < caps.length(); i++) { int cnt = caps.at(i).length(); - sels.insert(pos.at(idx), pos.at(cnt - 1 + idx)); + QPoint pt1 = pos.at(idx); + QPoint pt2 = pos.at(cnt - 1 + idx); + if(pt1.y() != pt2.y()) { + for(int i = idx; i <= cnt-1+idx; i++) { + QPoint pt = pos.at(i); + if(pt1.y() != pt.y()) { + sels.insert(pt1, pt2); + pt1 = pt2 = pt; + }else{ + pt2 = pt; + } + } + sels.insert(pt1, pt2); + }else{ + sels.insert(pt1, pt2); + } idx += cnt; } } diff --git a/private/languages/woterm_zh.ts b/private/languages/woterm_zh.ts index 9bc6be7..13b56cf 100644 --- a/private/languages/woterm_zh.ts +++ b/private/languages/woterm_zh.ts @@ -7491,63 +7491,63 @@ Please input password to activate it. 文件关联 - - - - - - - + + + + + + + Parameter error 参数错误 - + The start parameter does not contain a %1 placeholder 启动参数没有包含%1占位符 - + The priority parameter should be a number bigger than zero 优先级参数应该是大于0的数字 - + The application parameter should not be empty. 应该程序的参数不能为空。 - + The application is no permission to execute it 应用程序没有相应的执行权限 - + The file types parameter should not be empty. 文件类型参数不能为空。 - + Cannot be mixed with the star[*] symbol. 不能与星星[*]符号混用。 - + The format of the suffix name[%1] is incorrect and must start with a [.] character like [.%1]. 后缀名[%1]是错误表述,必须以[.]字符为首字符如[.%1]。 - + Execute file 执行程序 - + Execute program 执行程序 - + No permission to execute it 没有执行权限 @@ -9791,7 +9791,7 @@ Please input password to activate it. - + The directory is out of sync with the terminal. 文件夹不与终端同步 @@ -9827,59 +9827,69 @@ Please input password to activate it. - - - + + + Open file 打开文件 - - + + Failed to open: 打开失败: - + + Program file error + 程序错误 + + + + The program file has no permission to execute. + 程序文件没有可执行权限。 + + + Ready to submit file: %1 准备同步文件:%1 - - + + File synchronization 文件同步 - + Modify information 修改信息 - + The content has been modified. Do you need to submit it to the server? 内容已被修改。您需要将其提交到服务器吗? - - + + the follow files has exist or version restrictions: 以下文件已经存在或版本限制: - + Upload task 上传任务 - + Do you want to upload this related file? 是否继续上传相关文件? - - + + Select all 选择所有 @@ -9888,16 +9898,16 @@ Please input password to activate it. 返回 - - - - + + + + Refresh 刷新 - - + + Home Directory 返回主文件夹 @@ -9906,15 +9916,15 @@ Please input password to activate it. 创建文件夹 - - - + + + Upload 上传 - - + + Deselect all 取消所选 @@ -9923,14 +9933,14 @@ Please input password to activate it. 删除选中项 - + Modify the permission 修改文件权限 - - - + + + Rename 重命名 @@ -9939,13 +9949,13 @@ Please input password to activate it. 编辑文件 - + Move to other directory 移动至其它文件夹 - - + + Home directory 主文件夹 @@ -9954,176 +9964,176 @@ Please input password to activate it. 创建文件夹 - + &Edit file content 编辑文件内容(&E) - - + + &Open file 打开文件(&O) - + Try enter 尝试进入 - + Failure 失败 - + Failed to rename file for no permission to make path. 无法重命名文件,因为没有创建路径的权限。 - + directory name 文件夹名 - + Please input a directory name 请输入一个文件夹名称 - + information 信息 - + the new directory name should be empty! 新文件夹名不能为空! - - + + Remove file 删除文件 - - + + After deleting the file, it will not be recoverable. Please confirm whether to continue deleting the file. 删除文件后,该文件将无法恢复。请确认是否继续删除该文件。 - + Failed to open file: 无法打开文件: - + Input error 输入错误 - + The directory entered does not exist. 所输入的文件夹不存在。 - - + + File name 文件名称 - + Permission information 权限信息 - + Have other files also been modified with the same access permissions? 是否也使用相同的访问权限修改了其他文件? - + Move file 移动文件 - + Input a existing directory to save the selected file. 输入现有目录以保存所选文件。 - + Directory is not supported to edit. 文件夹不支持编辑。 - - + + The file size exceeding 5M bytes is not supported. 不支持超过5M字节的文件。 - + The target file exceeds 500K bytes. Do you want to continue editing? 目标文件超过500K字节。是否要继续编辑? - + Directory is not supported to view. 不支持查看目录。 - + The target file exceeds 500K bytes. Do you want to continue view? 目标文件超过500K字节。是否继续查看? - - + + SFTP SFTP - - + + No items are currently selected. 当前没有选中项 - + Keep the directory synchronized with the terminal. 保持文件夹与终端同步 - + Successfully submitted the modified file: %1 已成功提交修改后的文件:%1 - + Failed to submit the modified file: %1 无法提交修改后的文件:%1 - + The remote path[%1] does not exist or does not have permission to access it? 远程路径[%1]不存在或没有访问权限? - + Chmod - - - - - - - - + + + + + + + + File information 文件信息 @@ -10136,8 +10146,8 @@ Please input password to activate it. 删除文件夹 - - + + Enter 进入 @@ -10146,29 +10156,29 @@ Please input password to activate it. 删除文件 - - + + Download 下载 - + Try Enter 尝度进入 - + New Session Multiplex 新建连接复用 - + Close 关闭 - - + + Error 错误 @@ -10177,89 +10187,89 @@ Please input password to activate it. 保存文件 - - + + FileExist 文件存在 - - + + has the same name in the target path. override it? 已经存在同名文件,是否覆盖? - - + + Upload information 上传信息 - - + + the follow files has exist: 以下文件已经存在: - - - - + + + + &Back 返回(&B) - - + + &Create Directory 创建文件夹(&C) - - + + &Create File 创建文件(&C) - - + + &Delete selections 删除选中项(&D) - - + + &Create directory 创建文件夹(&C) - + Save directory 保存文件夹 - + Parameter error 参数错误 - + Please select directory to save it. 请选择文件夹去保存 - - + + Download information 下载信息 - + Select files 选择文件 - + Select File 选择文件 diff --git a/private/skins/black/desktop.qss b/private/skins/black/desktop.qss index 08e5f04..ab3fa30 100644 --- a/private/skins/black/desktop.qss +++ b/private/skins/black/desktop.qss @@ -406,4 +406,9 @@ QWidget[objectName="shortcut"] QPushButton { padding-right: 4px; padding-top: 0px; padding-bottom: 0px; -} \ No newline at end of file +} + +QKxBubbleSyncWidget { + padding: 5px; + border: 1px solid lightGray; +} diff --git a/private/skins/blue/desktop.qss b/private/skins/blue/desktop.qss index 9d7144f..cc19acb 100644 --- a/private/skins/blue/desktop.qss +++ b/private/skins/blue/desktop.qss @@ -395,4 +395,9 @@ QWidget[objectName="shortcut"] QPushButton { padding-right: 4px; padding-top: 0px; padding-bottom: 0px; -} \ No newline at end of file +} + +QKxBubbleSyncWidget { + padding: 5px; + border: 1px solid lightGray; +} diff --git a/private/skins/gold/desktop.qss b/private/skins/gold/desktop.qss index 05f3e73..3a80932 100644 --- a/private/skins/gold/desktop.qss +++ b/private/skins/gold/desktop.qss @@ -394,4 +394,9 @@ QWidget[objectName="shortcut"] QPushButton { padding-right: 4px; padding-top: 0px; padding-bottom: 0px; -} \ No newline at end of file +} + +QKxBubbleSyncWidget { + padding: 5px; + border: 1px solid lightGray; +} diff --git a/private/skins/light/desktop.qss b/private/skins/light/desktop.qss index b3d4060..6940c77 100644 --- a/private/skins/light/desktop.qss +++ b/private/skins/light/desktop.qss @@ -404,4 +404,9 @@ QWidget[objectName="shortcut"] QPushButton { padding-right: 4px; padding-top: 0px; padding-bottom: 0px; -} \ No newline at end of file +} + +QKxBubbleSyncWidget { + padding: 5px; + border: 1px solid lightGray; +} diff --git a/woterm/qkxbubblesyncwidget.cpp b/woterm/qkxbubblesyncwidget.cpp index 01ae4a2..5de6915 100644 --- a/woterm/qkxbubblesyncwidget.cpp +++ b/woterm/qkxbubblesyncwidget.cpp @@ -27,6 +27,7 @@ QKxBubbleSyncWidget::QKxBubbleSyncWidget(QWidget *parent) : setAttribute(Qt::WA_DeleteOnClose); QObject::connect(ui->btnClose, SIGNAL(clicked()), this, SLOT(close())); + setAttribute(Qt::WA_StyledBackground); ui->content->setReadOnly(true); diff --git a/woterm/qwosessionfileassociationadddialog.cpp b/woterm/qwosessionfileassociationadddialog.cpp index 0e13f01..423a4e8 100644 --- a/woterm/qwosessionfileassociationadddialog.cpp +++ b/woterm/qwosessionfileassociationadddialog.cpp @@ -57,7 +57,11 @@ QString QWoSessionFileAssociationAddDialog::application() const QString QWoSessionFileAssociationAddDialog::parameter() const { - return ui->parameter->text(); + QString params = ui->parameter->text(); + if(params.isEmpty()) { + return "\"{file}\""; + } + return params; } int QWoSessionFileAssociationAddDialog::priority() const @@ -67,7 +71,7 @@ int QWoSessionFileAssociationAddDialog::priority() const void QWoSessionFileAssociationAddDialog::onSaveButtonClicked() { - QString params = ui->parameter->text(); + QString params = parameter(); if(!params.contains("{file}")) { QKxMessageBox::information(this, tr("Parameter error"), tr("The start parameter does not contain a %1 placeholder").arg("{file}")); return; diff --git a/woterm/qwosftpwidget.cpp b/woterm/qwosftpwidget.cpp index 355379a..3f1029b 100644 --- a/woterm/qwosftpwidget.cpp +++ b/woterm/qwosftpwidget.cpp @@ -496,7 +496,7 @@ void QWoSftpWidget::handleView(const QString &fileSave, const QString &fileRemot QKxMessageBox::information(this, tr("File error"), tr("The temp file has been lost.")); return; } - if(!QDesktopServices::openUrl(QUrl::fromLocalFile(fileSave))){ + if(!QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absoluteFilePath()))){ QKxMessageBox::information(this, tr("Open file"), tr("Failed to open:")+fi.fileName()); } } @@ -521,8 +521,18 @@ void QWoSftpWidget::handleEdit(const QString &fileSave, const QString &fileRemot QKxMessageBox::information(this, tr("File error"), tr("The temp file has been lost.")); return; } - QString params = fa.parameter.replace("{file}", fileSave); - openEditor(fa.application + " " + params, fileSave, fileRemote, fi.lastModified()); + + QFileInfo app(fa.application); + if(!app.isExecutable()) { + QKxMessageBox::information(this, tr("Program file error"), tr("The program file has no permission to execute.")); + return; + } + + QString fileEdit = QDir::toNativeSeparators(fi.absoluteFilePath()); + QString params = fa.parameter.replace("{file}", fileEdit); + QString application = QDir::toNativeSeparators(app.absoluteFilePath()); + QString cmd = QString("\"%1\" %2").arg(application).arg(params); + openEditor(cmd, fileSave, fileRemote, fi.lastModified()); } bool QWoSftpWidget::handleEditCommit(const QString &fileSave, const QString &fileRemote, const qint64& dt, bool force) diff --git a/woterm/version.h b/woterm/version.h index 290fdb3..2c3d48a 100644 --- a/woterm/version.h +++ b/woterm/version.h @@ -1,4 +1,4 @@ #pragma once -#define WOTERM_VERSION ("9.29.2") +#define WOTERM_VERSION ("9.29.3") #define NOISE