Skip to content

Commit

Permalink
src:Add enhancements and fix issues in quardCRT
Browse files Browse the repository at this point in the history
The commit includes enhancements to the Windows terminal, such as the
ability to use the Tab key for command completion, and fixes an issue
with macOS shortcut keys. Additionally, the commit includes updates to
various files related to child process information.

Signed-off-by: xiaoming <2014500726@smail.xtu.edu.cn>
  • Loading branch information
QQxiaoming committed Nov 12, 2023
1 parent e69ea8b commit d69a767
Show file tree
Hide file tree
Showing 13 changed files with 166 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
## [[Unrelease](https://github.com/QQxiaoming/quardCRT)]

- 增加标签卡悬浮预览功能
- windows终端增强,现在可以像linux一样使用Tab键选择补全命令
- 修复macOS错误绑定了复制粘贴快捷键导致无法kill终端内进程问题

## [[V0.2.5](https://github.com/QQxiaoming/quardCRT/releases/tag/V0.2.5)] - 2023-11-09

Expand Down
36 changes: 36 additions & 0 deletions lib/ptyqt/conptyprocess.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "conptyprocess.h"
#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <QFile>
#include <QFileInfo>
#include <QDir>
Expand Down Expand Up @@ -326,6 +327,41 @@ bool ConPtyProcess::hasChildProcess()
return false;
}

QList<QPair<int, QString>> ConPtyProcess::childProcessInfoList()
{
QList<QPair<int, QString>> result;

HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

if (snapshot == INVALID_HANDLE_VALUE)
return result;

PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);

if (Process32First(snapshot, &pe)) {
do {
if (pe.th32ParentProcessID == m_pid) {
// get full path
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe.th32ProcessID);
if (hProcess != NULL)
{
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
if (GetModuleFileNameExW(hProcess, NULL, szProcessName, MAX_PATH) != 0)
{
QPair<int, QString> pair = QPair<int, QString>(pe.th32ProcessID, QString::fromWCharArray(szProcessName));
result.append(pair);
}
CloseHandle(hProcess);
}
}
} while (Process32Next(snapshot, &pe));
}

CloseHandle(snapshot);
return result;
}

bool ConPtyProcess::isAvailable()
{
#ifdef TOO_OLD_WINSDK
Expand Down
1 change: 1 addition & 0 deletions lib/ptyqt/conptyprocess.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ class ConPtyProcess : public IPtyProcess
virtual qint64 write(const QByteArray &byteArray);
virtual QString currentDir();
virtual bool hasChildProcess();
virtual QList<QPair<int, QString>> childProcessInfoList();
bool isAvailable();
void moveToThread(QThread *targetThread);

Expand Down
1 change: 1 addition & 0 deletions lib/ptyqt/iptyprocess.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class IPtyProcess
virtual bool isAvailable() = 0;
virtual void moveToThread(QThread *targetThread) = 0;
virtual bool hasChildProcess() = 0;
virtual QList<QPair<int, QString>> childProcessInfoList() = 0;
qint64 pid() { return m_pid; }
QPair<qint16, qint16> size() { return m_size; }
const QString lastError() { return m_lastError; }
Expand Down
2 changes: 1 addition & 1 deletion lib/ptyqt/ptyqt.pri
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ win32:{
$$PWD/conptyprocess.cpp \
$$PWD/winptyprocess.cpp

WINPTY_DIR=D:\quardCRT\depend\winpty
WINPTY_DIR=D:\\winpty
INCLUDEPATH += $${WINPTY_DIR}\include\winpty
LIBS += $${WINPTY_DIR}\lib\winpty.lib

Expand Down
56 changes: 51 additions & 5 deletions lib/ptyqt/unixptyprocess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -319,13 +319,59 @@ QString UnixPtyProcess::currentDir()

bool UnixPtyProcess::hasChildProcess()
{
int pid = tcgetpgrp(m_shellProcess.m_handleMaster);
if ( pid != -1 ) {
if(m_pid != pid) {
return true;
QList<QPair<int, QString>> childList = childProcessInfoList();
return (childList.size() > 0);
}

QList<QPair<int, QString>> UnixPtyProcess::childProcessInfoList()
{
QList<QPair<int, QString>> result;
QString cmd = QString("ps");
QStringList args = { "-o", "pid,ppid,pgid,command", "-ax" };
QProcess ps;
ps.start(cmd, args);
ps.waitForFinished(-1);
QString psResult = ps.readAllStandardOutput();
QStringList psLines = psResult.split("\n");
foreach (QString line, psLines)
{
if (line.contains("PID"))
continue;

QStringList lineParts = line.split(" ");
QStringList linePartsFiltered;
foreach (QString part, lineParts)
{
if (!part.isEmpty())
linePartsFiltered.append(part);
}
if (linePartsFiltered.size() < 4)
continue;

QString pid = linePartsFiltered.at(0);
QString ppid = linePartsFiltered.at(1);
QString pgid = linePartsFiltered.at(2);
QString command = linePartsFiltered.at(3);
QStringList arg = linePartsFiltered.mid(4);

if (pid == QString::number(m_pid))
continue;

if (ppid == QString::number(m_pid))
{
QPair<int, QString> pair = QPair<int, QString>(pid.toInt(), command+" "+arg.join(" "));
result.push_back(pair);
continue;
}

if (pgid == QString::number(m_pid))
{
QPair<int, QString> pair = QPair<int, QString>(pid.toInt(), command+" "+arg.join(" "));
result.push_back(pair);
continue;
}
}
return false;
return result;
}

bool UnixPtyProcess::isAvailable()
Expand Down
1 change: 1 addition & 0 deletions lib/ptyqt/unixptyprocess.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ class UnixPtyProcess : public IPtyProcess
virtual qint64 write(const QByteArray &byteArray);
virtual QString currentDir();
virtual bool hasChildProcess();
virtual QList<QPair<int, QString>> childProcessInfoList();
virtual bool isAvailable();
void moveToThread(QThread *targetThread);

Expand Down
36 changes: 36 additions & 0 deletions lib/ptyqt/winptyprocess.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "winptyprocess.h"
#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <QFile>
#include <QFileInfo>
#include <sstream>
Expand Down Expand Up @@ -264,6 +265,41 @@ bool WinPtyProcess::hasChildProcess()
return false;
}

QList<QPair<int, QString>> WinPtyProcess::childProcessInfoList()
{
QList<QPair<int, QString>> result;

HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

if (snapshot == INVALID_HANDLE_VALUE)
return result;

PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);

if (Process32First(snapshot, &pe)) {
do {
if (pe.th32ParentProcessID == m_pid) {
// get full path
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pe.th32ProcessID);
if (hProcess != NULL)
{
TCHAR szProcessName[MAX_PATH] = TEXT("<unknown>");
if (GetModuleFileNameExW(hProcess, NULL, szProcessName, MAX_PATH) != 0)
{
QPair<int, QString> pair = QPair<int, QString>(pe.th32ProcessID, QString::fromWCharArray(szProcessName));
result.append(pair);
}
CloseHandle(hProcess);
}
}
} while (Process32Next(snapshot, &pe));
}

CloseHandle(snapshot);
return result;
}

bool WinPtyProcess::isAvailable()
{
return QFile::exists(QCoreApplication::applicationDirPath() + "/" + WINPTY_AGENT_NAME)
Expand Down
1 change: 1 addition & 0 deletions lib/ptyqt/winptyprocess.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class WinPtyProcess : public IPtyProcess
qint64 write(const QByteArray &byteArray);
QString currentDir();
virtual bool hasChildProcess();
virtual QList<QPair<int, QString>> childProcessInfoList();
bool isAvailable();
void moveToThread(QThread *targetThread);

Expand Down
4 changes: 4 additions & 0 deletions scripts/Profile.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,7 @@ function prompt {

return $out
}

Set-PSReadlineKeyHandler -Key Tab -Function MenuComplete
Set-PSReadlineKeyHandler -Key UpArrow -Function HistorySearchBackward
Set-PSReadlineKeyHandler -Key DownArrow -Function HistorySearchForward
8 changes: 4 additions & 4 deletions src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -748,17 +748,17 @@ void MainWindow::menuAndToolBarRetranslateUi(void) {
copyAction->setText(tr("Copy"));
copyAction->setIcon(QFontIcon::icon(QChar(0xf0c5)));
#if defined(Q_OS_MACOS)
copyAction->setStatusTip(tr("Copy the selected text to the clipboard <Ctrl+C>"));
copyAction->setShortcut(QKeySequence(Qt::META|Qt::Key_C));
copyAction->setStatusTip(tr("Copy the selected text to the clipboard <Command+C>"));
copyAction->setShortcut(QKeySequence(Qt::CTRL|Qt::Key_C));
#else
copyAction->setStatusTip(tr("Copy the selected text to the clipboard <Ctrl+Ins>"));
copyAction->setShortcut(QKeySequence(Qt::CTRL|Qt::Key_Insert));
#endif
pasteAction->setText(tr("Paste"));
pasteAction->setIcon(QFontIcon::icon(QChar(0xf0ea)));
#if defined(Q_OS_MACOS)
pasteAction->setStatusTip(tr("Paste the clipboard text to the current session <Ctrl+V>"));
pasteAction->setShortcut(QKeySequence(Qt::META|Qt::Key_V));
pasteAction->setStatusTip(tr("Paste the clipboard text to the current session <Command+V>"));
pasteAction->setShortcut(QKeySequence(Qt::CTRL|Qt::Key_V));
#else
pasteAction->setStatusTip(tr("Paste the clipboard text to the current session <Shift+Ins>"));
pasteAction->setShortcut(QKeySequence(Qt::SHIFT|Qt::Key_Insert));
Expand Down
27 changes: 27 additions & 0 deletions src/sessionswindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -542,3 +542,30 @@ bool SessionsWindow::hasChildProcess() {
}
}

QString SessionsWindow::getStateInfo() {
switch(type) {
case LocalShell:{
QList<QPair<int, QString>> list = localShell->childProcessInfoList();
if(list.isEmpty()) return tr("No child process.");
QString ret = "<table border='0' width='100%'>";
ret += "<tr><th width='30%'>PID</th><th width='70%'>Command</th></tr>";
foreach(auto info, list) {
ret += "<tr><td width='30%'>"
+ QString::number(info.first)
+ "</td><td width='70%'>"
+ info.second
+ "</td></tr>";
}
ret += "</table>";
return ret;
}
case Telnet:
return tr("Telnet %1:%2").arg(m_hostname).arg(m_port);
case Serial:
return tr("Serial %1 %2 %3 %4 %5 %6 %7").arg(m_portName).arg(m_baudRate).arg(m_dataBits).arg(m_parity).arg(m_stopBits).arg(m_flowControl).arg(m_xEnable);
case RawSocket:
return tr("Raw Socket %1:%2").arg(m_hostname).arg(m_port);
case NamePipe:
return tr("Name Pipe %1").arg(m_pipeName);
}
}
1 change: 1 addition & 0 deletions src/sessionswindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ class SessionsWindow : public QObject
bool isLocked() const { return locked; }
SessionsState getState() const { return state; }
bool hasChildProcess();
QString getStateInfo();

QString getHostname() const { return m_hostname; }
quint16 getPort() const { return m_port; }
Expand Down

0 comments on commit d69a767

Please sign in to comment.