debug:初步显示远端文件。

This commit is contained in:
taynpg 2025-05-12 22:07:06 +08:00
parent 7bf936fa8f
commit de46e40e0c
13 changed files with 358 additions and 9 deletions

View File

@ -4,11 +4,17 @@ project(ClientCore LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if (MSVC)
add_compile_options(/utf-8)
endif()
find_package(wxWidgets CONFIG REQUIRED)
set(MSOURCES
ClientCore.h
ClientCore.cxx
ClientFile.h
ClientFile.cxx
)
add_library(ClientCore STATIC ${MSOURCES})

View File

@ -52,6 +52,11 @@ wxString ClientCore::GetErr() const
return err_;
}
wxString ClientCore::GetOwnId() const
{
return id_;
}
bool ClientCore::IsOk()
{
return socket_->IsConnected();
@ -76,6 +81,16 @@ void ClientCore::ReqOnlineCallback(const std::function<void(const InfoClientVec&
onlineCallback_ = callback;
}
void ClientCore::SetHomeCallback(const std::function<void(const wxString&)>& callback)
{
homeCall_ = callback;
}
void ClientCore::SetDirFileCallback(const std::function<void(const DirFileInfoVec&)>& callback)
{
dirFileCall_ = callback;
}
bool ClientCore::AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec)
{
return false;
@ -121,6 +136,42 @@ void ClientCore::UseFrame(FrameBuffer* buf)
InfoCommunicate info;
break;
}
case FBT_CLI_ASK_HOME: {
InfoCommunicate info;
wxString home = wxGetHomeDir();
info.data = home.ToStdString();
Send<InfoCommunicate>(info, FBT_CLI_ANS_HOME, buf->fid);
break;
}
case FBT_CLI_ANS_HOME: {
InfoCommunicate info;
ZeroCopyInput input(buf->dataMut, buf->len);
input.archive() >> info;
if (homeCall_) {
homeCall_(info.data);
}
break;
}
case FBT_CLI_ASK_DIRFILE: {
InfoCommunicate info;
ZeroCopyInput input(buf->dataMut, buf->len);
input.archive() >> info;
DirFileInfoVec vec;
if (!cf_.GetDirFiles(info.data, vec)) {
break;
}
Send<DirFileInfoVec>(vec, FBT_CLI_ANS_DIRFILE, buf->fid);
break;
}
case FBT_CLI_ANS_DIRFILE: {
DirFileInfoVec vec;
ZeroCopyInput input(buf->dataMut, buf->len);
input.archive() >> vec;
if (dirFileCall_) {
dirFileCall_(vec);
}
break;
}
default:
break;
}

View File

@ -1,15 +1,16 @@
#ifndef CLIENTCORE_H
#define CLIENTCORE_H
#include "ClientFile.h"
#include <InfoClient.hpp>
#include <InfoCommunicate.hpp>
#include <InfoDirFile.hpp>
#include <array>
#include <cstdint>
#include <memory>
#include <vector>
#include <thread>
#include <functional>
#include <memory>
#include <thread>
#include <vector>
#include <wx/socket.h>
#include <Communicate.h>
@ -27,12 +28,17 @@ public:
public:
wxString GetErr() const;
wxString GetOwnId() const;
bool IsOk();
void SetLogCallback(const std::function<void(const wxString&)>& callback);
bool ReqOnline();
void ReqOnlineCallback(const std::function<void(const InfoClientVec&)>& callback);
bool AskDirectory(const wxString& id, const wxString& path, DirFileInfoVec& dirInfoVec);
public:
void ReqOnlineCallback(const std::function<void(const InfoClientVec&)>& callback);
void SetHomeCallback(const std::function<void(const wxString&)>& callback);
void SetDirFileCallback(const std::function<void(const DirFileInfoVec&)>& callback);
private:
void UseFrame(FrameBuffer* buf);
@ -42,7 +48,9 @@ private:
private:
void HeartBeat();
void Recv();
template <typename T> bool Send(const T& info, FrameBufferType type)
public:
template <typename T> bool Send(const T& info, FrameBufferType type, const wxString& remoteId = wxEmptyString)
{
std::stringstream ss;
cereal::BinaryOutputArchive archive(ss);
@ -52,6 +60,7 @@ private:
buf->dataConst = ss.view().data();
buf->len = ss.str().size();
buf->dataType = type;
buf->tid = remoteId.ToStdString();
return Send(buf.get());
}
@ -62,13 +71,16 @@ private:
bool thRun_;
MutBuffer buffer_;
wxString err_;
ClientFile cf_;
std::thread recvThread_;
std::array<char, GBUFFER_SIZE> buf_;
wxSocketClient* socket_;
private:
std::function<void(const DirFileInfoVec&)> dirFileCall_;
std::function<void(const InfoClientVec&)> onlineCallback_;
std::function<void(const wxString&)> logCall_;
std::function<void(const wxString&)> homeCall_;
};
#endif // CLIENTCORE_H

65
ClientCore/ClientFile.cxx Normal file
View File

@ -0,0 +1,65 @@
#include "ClientFile.h"
#include <wx/dir.h>
ClientFile::ClientFile()
{
}
bool ClientFile::GetDirFiles(const std::string& path, DirFileInfoVec& vec)
{
if (!fs::exists(path)) {
lastErr_ = wxString::Format(_("Path does not exist: %s"), path);
return false;
}
if (!fs::is_directory(path)) {
lastErr_ = wxString::Format(_("Not a directory: %s"), path);
return false;
}
vec.vec.clear();
try {
// 遍历目录
for (const auto& entry : fs::directory_iterator(path)) {
DirFileInfo info;
const auto& path = entry.path();
// 设置基本信息
info.fullPath = path.string();
info.name = path.filename().string();
// 设置类型
if (entry.is_directory()) {
info.type = Dir;
info.size = 0;
} else if (entry.is_regular_file()) {
info.type = File;
info.size = entry.file_size();
} else {
// 跳过符号链接、设备文件等
continue;
}
// 获取最后修改时间
auto ftime = entry.last_write_time();
auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
ftime - fs::file_time_type::clock::now() + std::chrono::system_clock::now());
info.lastModifyTime = std::chrono::system_clock::to_time_t(sctp);
vec.vec.push_back(info);
}
} catch (const fs::filesystem_error& e) {
lastErr_ = wxString::FromUTF8(e.what());
return false;
} catch (const std::exception& e) {
lastErr_ = wxString::FromUTF8(e.what());
return false;
}
return true;
}
wxString ClientFile::GetLastErr() const
{
return lastErr_;
}

21
ClientCore/ClientFile.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef CLIENTFILE_H
#define CLIENTFILE_H
#include <InfoDirFile.hpp>
#include <filesystem>
namespace fs = std::filesystem;
class ClientFile
{
public:
ClientFile();
public:
bool GetDirFiles(const std::string& path, DirFileInfoVec& vec);
wxString GetLastErr() const;
private:
wxString lastErr_;
};
#endif // CLIENTFILE_H

View File

@ -17,6 +17,47 @@ enum FileType : uint32_t {
};
struct DirFileInfo {
static wxString GetFileSize(uint64_t size)
{
const uint64_t KB = 1024;
const uint64_t MB = KB * 1024;
const uint64_t GB = MB * 1024;
if (size >= GB) {
return wxString::Format("%.2f GB", static_cast<double>(size) / GB);
} else if (size >= MB) {
return wxString::Format("%.2f MB", static_cast<double>(size) / MB);
} else if (size >= KB) {
return wxString::Format("%.2f KB", static_cast<double>(size) / KB);
} else {
return wxString::Format("%llu B", size);
}
}
static wxString GetStrTime(uint64_t time)
{
wxDateTime dt(static_cast<time_t>(time));
wxString dateStr = dt.Format("%Y/%m/%d %H:%M:%S");
return dateStr;
}
static wxString GetFileTypeName(FileType type)
{
switch (type) {
case None:
return _("None");
case File:
return _("File");
case Dir:
return _("Dir");
case Link:
return _("Link");
default:
return _("Unknown");
}
}
std::string name;
uint64_t size = 0;
FileType type = None;

View File

@ -12,7 +12,10 @@ enum FrameBufferType : uint16_t {
FBT_SER_MSG_RESPONSE,
FBT_CLI_BIN_FILEDATA = 31,
FBT_CLI_MSG_COMMUNICATE,
FBT_CLI_INFO_DIRFILE
FBT_CLI_ASK_DIRFILE,
FBT_CLI_ANS_DIRFILE,
FBT_CLI_ASK_HOME,
FBT_CLI_ANS_HOME
};
struct FrameBuffer {

View File

@ -10,13 +10,15 @@ void ControlManager::Init(std::shared_ptr<ClientCore>& clientCore)
log_ = new LogControl(parent_);
header_ = new HeaderControl(parent_, clientCore);
local_ = new LocalControl(parent_);
remote_ = new RemoteControl(parent_);
remote_ = new RemoteControl(parent_, clientCore);
task_ = new TaskControl(parent_);
online_ = new OnlineControl(parent_, clientCore);
header_->SetLogControl(log_);
online_->SetLogControl(log_);
header_->SetOnlineControl(online_);
online_->SetRemoteControl(remote_);
remote_->SetLogControl(log_);
clientCore->SetLogCallback([this](const wxString& msg) { log_->AddLog(msg); });
}

View File

@ -7,6 +7,7 @@
class LogControl;
class ClientCore;
class OnlineControl;
class RemoteControl;
class HeaderControl : public wxPanel
{
public:
@ -16,6 +17,7 @@ public:
public:
void SetLogControl(LogControl* logControl);
void SetOnlineControl(OnlineControl* onlineControl);
void SetRemoteControl(RemoteControl* remoteControl);
private:
void Init();

View File

@ -1,12 +1,14 @@
#include "OnLineControl.h"
#include "HeaderControl.h"
#include "LogControl.h"
#include "RemoteControl.h"
#include <ClientCore.h>
OnlineControl::OnlineControl(wxWindow* parent, std::shared_ptr<ClientCore>& clientCore) : wxPanel(parent), clientCore_(clientCore)
{
Init();
InitCall();
BindEvent();
}
OnlineControl::~OnlineControl()
@ -23,6 +25,11 @@ void OnlineControl::SetLogControl(LogControl* logControl)
logControl_ = logControl;
}
void OnlineControl::SetRemoteControl(RemoteControl* remoteControl)
{
remoteControl_ = remoteControl;
}
void OnlineControl::Init()
{
btnFresh_ = new wxButton(this, wxID_ANY, _("Refresh"));
@ -30,6 +37,8 @@ void OnlineControl::Init()
elbCurState_ = new wxStaticText(this, wxID_ANY, _("Disconnected"));
elbCurState_->SetForegroundColour(*wxBLUE);
onLineList_ = new wxListBox(this, wxID_ANY);
// 设置 onLineList_ 只能单选
onLineList_->SetWindowStyle(wxLB_SINGLE);
lbCurPoint_ = new wxStaticText(this, wxID_ANY, _("Commnunicate Point => "));
elbCurPoint_ = new wxStaticText(this, wxID_ANY, _("None"));
@ -51,7 +60,20 @@ void OnlineControl::Init()
SetSizer(topSizer);
Layout();
menu_ = new wxMenu;
useId_ = wxNewId();
menu_->Append(useId_, _("Use this client"));
}
void OnlineControl::BindEvent()
{
Bind(wxEVT_BUTTON, &OnlineControl::OnFreshClients, this, btnFresh_->GetId());
onLineList_->Bind(wxEVT_CONTEXT_MENU, [&](wxContextMenuEvent& event) {
auto p = event.GetPosition();
p = onLineList_->ScreenToClient(p);
onLineList_->PopupMenu(menu_, p);
});
Bind(wxEVT_MENU, &OnlineControl::UseThisClient, this, useId_);
}
void OnlineControl::SetConnectState(const wxString& state)
@ -98,3 +120,20 @@ void OnlineControl::OnFreshClientsCall(const InfoClientVec& infoClientVec)
}
logControl_->AddLog(_("Get online list success."));
}
void OnlineControl::UseThisClient(wxCommandEvent& event)
{
int selection = onLineList_->GetSelection();
if (selection != wxNOT_FOUND) {
wxString selectedText = onLineList_->GetString(selection);
if (clientCore_->GetOwnId() == selectedText) {
wxMessageDialog dialog(this, _("You selected yourself, do you want to use yourself?"), _("Confirm"),
wxYES_NO | wxICON_QUESTION);
if (dialog.ShowModal() == wxID_YES) {
remoteControl_->setRemoteID(selectedText);
}
return;
}
remoteControl_->setRemoteID(selectedText);
}
}

View File

@ -8,6 +8,7 @@
class HeaderControl;
class LogControl;
class ClientCore;
class RemoteControl;
class OnlineControl : public wxPanel
{
public:
@ -16,6 +17,7 @@ public:
public:
void SetHeaderControl(HeaderControl* headerControl);
void SetRemoteControl(RemoteControl* remoteControl);
void SetLogControl(LogControl* logControl);
void SetConnectState(const wxString& state);
void SetConnectServer(const wxString& server);
@ -24,10 +26,12 @@ public:
private:
void Init();
void InitCall();
void BindEvent();
void OnFreshClients(wxCommandEvent& event);
private:
void OnFreshClientsCall(const InfoClientVec& infoClientVec);
void UseThisClient(wxCommandEvent& event);
public:
wxButton* btnFresh_;
@ -39,7 +43,12 @@ public:
wxListBox* onLineList_;
HeaderControl* headerControl_;
LogControl* logControl_;
wxMenu* menu_;
RemoteControl* remoteControl_;
std::shared_ptr<ClientCore> clientCore_;
private:
wxWindowID useId_;
};
#endif // ONLINECONTROL_H

View File

@ -1,9 +1,13 @@
#include "RemoteControl.h"
#include "LogControl.h"
#include <ClientCore.h>
#include <InfoCommunicate.hpp>
RemoteControl::RemoteControl(wxWindow* parent) : wxPanel(parent)
RemoteControl::RemoteControl(wxWindow* parent, std::shared_ptr<ClientCore>& clientCore) : wxPanel(parent), clientCore_(clientCore)
{
Init();
SetGrid();
BindEvent();
}
RemoteControl::~RemoteControl()
@ -19,6 +23,11 @@ void RemoteControl::Init()
textCtrl_ = new wxTextCtrl(this, wxID_ANY);
dirSizer->Add(textCtrl_, 1, wxALL | wxEXPAND, gBorder);
edRemoteId_ = new wxTextCtrl(this, wxID_ANY);
edRemoteId_->SetMinSize(wxSize(200, -1));
edRemoteId_->SetEditable(false);
dirSizer->Add(edRemoteId_, 0, wxALL | wxCENTER, gBorder);
btnHome_ = new wxButton(this, wxID_ANY, _("Home"));
dirSizer->Add(btnHome_, 0, wxALL | wxCENTER, gBorder);
@ -40,6 +49,66 @@ void RemoteControl::Init()
Layout();
}
void RemoteControl::BindEvent()
{
Bind(wxEVT_BUTTON, &RemoteControl::AskHome, this, btnHome_->GetId());
clientCore_->SetHomeCallback([this](const wxString& home) {
textCtrl_->SetValue(home);
logControl_->AddLog(_("Remote Home: %s"), home);
});
Bind(wxEVT_BUTTON, &RemoteControl::GetDirContent, this, btnGet_->GetId());
clientCore_->SetDirFileCallback([this](const DirFileInfoVec& dirInfoVec) {
if (grid_->GetNumberRows() > 0) {
grid_->DeleteRows(0, grid_->GetNumberRows());
}
for (auto& dirInfo : dirInfoVec.vec) {
grid_->AppendRows();
auto wxPath = wxString::FromUTF8(dirInfo.fullPath);
grid_->SetCellValue(grid_->GetNumberRows() - 1, 0, wxPath);
grid_->SetCellValue(grid_->GetNumberRows() - 1, 1, DirFileInfo::GetFileSize(dirInfo.size));
grid_->SetCellValue(grid_->GetNumberRows() - 1, 2, DirFileInfo::GetFileTypeName(dirInfo.type));
grid_->SetCellValue(grid_->GetNumberRows() - 1, 3, DirFileInfo::GetStrTime(dirInfo.lastModifyTime));
grid_->SetCellValue(grid_->GetNumberRows() - 1, 4, wxString::Format("%o", dirInfo.permission));
}
});
}
void RemoteControl::AskHome(wxCommandEvent& event)
{
auto remoteId = edRemoteId_->GetValue();
if (remoteId.empty()) {
logControl_->AddLog(_("Remote ID is Empty."));
return;
}
InfoCommunicate infoCommunicate;
if (!clientCore_->Send<InfoCommunicate>(infoCommunicate, FBT_CLI_ASK_HOME, remoteId)) {
logControl_->AddLog(_("Request ask %s's Home Failed"), remoteId);
} else {
logControl_->AddLog(_("Request ask %s's Home Success"), remoteId);
}
}
void RemoteControl::GetDirContent(wxCommandEvent& event)
{
auto remoteId = edRemoteId_->GetValue();
if (remoteId.empty()) {
logControl_->AddLog(_("Remote ID is Empty."));
return;
}
auto home = textCtrl_->GetValue();
if (home.empty()) {
logControl_->AddLog(_("Remote Home is Empty."));
return;
}
InfoCommunicate info;
info.data = home.ToStdString();
if (!clientCore_->Send<InfoCommunicate>(info, FBT_CLI_ASK_DIRFILE, remoteId)) {
logControl_->AddLog(_("Request get %s's DirFile Failed"), home);
} else {
logControl_->AddLog(_("Request get %s's DirFile Success"), home);
}
}
void RemoteControl::SetGrid()
{
grid_->CreateGrid(10, 5);
@ -55,3 +124,14 @@ void RemoteControl::SetGrid()
grid_->SetColSize(3, 150);
grid_->SetColSize(4, 100);
}
void RemoteControl::setRemoteID(const wxString& id)
{
logControl_->AddLog(_("You Selected Remote ID: ") + id);
edRemoteId_->SetValue(id);
}
void RemoteControl::SetLogControl(LogControl* logControl)
{
logControl_ = logControl;
}

View File

@ -4,23 +4,41 @@
#include "InterfaceDefine.hpp"
#include <wx/grid.h>
class LogControl;
class ClientCore;
class RemoteControl : public wxPanel
{
public:
RemoteControl(wxWindow* parent);
RemoteControl(wxWindow* parent, std::shared_ptr<ClientCore>& clientCore);
~RemoteControl() override;
public:
void setRemoteID(const wxString& id);
public:
void SetLogControl(LogControl* logControl);
private:
void Init();
void SetGrid();
void BindEvent();
private:
void AskHome(wxCommandEvent& event);
void GetDirContent(wxCommandEvent& event);
public:
wxGrid* grid_;
wxTextCtrl* textCtrl_;
wxTextCtrl* edRemoteId_;
wxButton* btnHome_;
wxButton* btnGet_;
wxButton* btnUpLevel_;
wxButton* btnRefresh_;
private:
LogControl* logControl_;
std::shared_ptr<ClientCore> clientCore_;
};
#endif // REMOTECONTROL_H