mirror of
https://github.com/Adaptix-Framework/AdaptixC2
synced 2026-06-08 10:20:39 +00:00
Client: DownloadsWidget
This commit is contained in:
@@ -80,7 +80,7 @@ func (ts *Teamserver) TsDownloadUpdate(fileId string, state int, data []byte) er
|
||||
|
||||
downloadData.State = state
|
||||
|
||||
if len(data) == 0 {
|
||||
if len(data) > 0 {
|
||||
_, err := downloadData.File.Write(data)
|
||||
if err != nil {
|
||||
downloadData.File, err = os.Create(downloadData.LocalPath)
|
||||
@@ -126,7 +126,8 @@ func (ts *Teamserver) TsDownloadFinish(fileId string, state int) error {
|
||||
if downloadData.State == DOWNLOAD_STATE_CANCELED {
|
||||
os.Remove(downloadData.LocalPath)
|
||||
ts.downloads.Delete(fileId)
|
||||
} else if downloadData.State == DOWNLOAD_STATE_FINISHED {
|
||||
} else {
|
||||
downloadData.State = DOWNLOAD_STATE_FINISHED
|
||||
ts.downloads.Put(downloadData.FileId, downloadData)
|
||||
}
|
||||
|
||||
|
||||
@@ -219,12 +219,13 @@ func CreateSpDownloadCreate(downloadData DownloadData) SyncPackerDownloadCreate
|
||||
store: STORE_LOG,
|
||||
SpType: TYPE_DOWNLOAD_CREATE,
|
||||
|
||||
AgentId: downloadData.AgentId,
|
||||
FileId: downloadData.FileId,
|
||||
Computer: downloadData.Computer,
|
||||
File: downloadData.RemotePath,
|
||||
Size: downloadData.TotalSize,
|
||||
Date: downloadData.Date,
|
||||
AgentId: downloadData.AgentId,
|
||||
AgentName: downloadData.AgentName,
|
||||
FileId: downloadData.FileId,
|
||||
Computer: downloadData.Computer,
|
||||
File: downloadData.RemotePath,
|
||||
Size: downloadData.TotalSize,
|
||||
Date: downloadData.Date,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ SET( HEADERS
|
||||
Headers/Agent/TableWidgetItemAgent.h
|
||||
Headers/Client/LastTickWorker.h
|
||||
Headers/Agent/Commander.h
|
||||
Headers/UI/Widgets/DownloadsWidget.h
|
||||
)
|
||||
|
||||
add_executable(AdaptixClient
|
||||
@@ -79,6 +80,7 @@ add_executable(AdaptixClient
|
||||
Source/Agent/TableWidgetItemAgent.cpp
|
||||
Source/Client/LastTickWorker.cpp
|
||||
Source/Agent/Commander.cpp
|
||||
Source/UI/Widgets/DownloadWidget.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(AdaptixClient
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <UI/Widgets/LogsWidget.h>
|
||||
#include <UI/Widgets/ListenersWidget.h>
|
||||
#include <UI/Widgets/SessionsTableWidget.h>
|
||||
#include <UI/Widgets/DownloadsWidget.h>
|
||||
#include <Client/WidgetBuilder.h>
|
||||
#include <Agent/Agent.h>
|
||||
|
||||
@@ -55,12 +56,14 @@ public:
|
||||
LogsWidget* LogsTab = nullptr;
|
||||
ListenersWidget* ListenersTab = nullptr;
|
||||
SessionsTableWidget* SessionsTablePage = nullptr;
|
||||
DownloadsWidget* DownloadsTab = nullptr;
|
||||
|
||||
QMap<QString, Commander*> RegisterAgentsCmd;
|
||||
QMap<QString, WidgetBuilder*> RegisterAgentsUI;
|
||||
QMap<QString, WidgetBuilder*> RegisterListenersUI;
|
||||
QMap<QString, QStringList> LinkListenerAgent;
|
||||
QVector<ListenerData> Listeners;
|
||||
QMap<QString, DownloadData> Downloads;
|
||||
QMap<QString, Agent*> Agents;
|
||||
|
||||
explicit AdaptixWidget(AuthProfile authProfile);
|
||||
@@ -76,6 +79,7 @@ public slots:
|
||||
|
||||
void LoadLogsUI();
|
||||
void LoadListenersUI();
|
||||
void LoadDownloadsUI();
|
||||
void LoadConsoleUI(QString AgentId);
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#ifndef ADAPTIXCLIENT_DOWNLOADSWIDGET_H
|
||||
#define ADAPTIXCLIENT_DOWNLOADSWIDGET_H
|
||||
|
||||
#include <main.h>
|
||||
|
||||
class DownloadsWidget : public QWidget
|
||||
{
|
||||
QWidget* mainWidget = nullptr;
|
||||
QTableWidget* tableWidget = nullptr;
|
||||
QGridLayout* mainGridLayout = nullptr;
|
||||
|
||||
void createUI();
|
||||
|
||||
public:
|
||||
DownloadsWidget(QWidget* w);
|
||||
~DownloadsWidget();
|
||||
|
||||
void AddDownloadItem(DownloadData newDownload);
|
||||
void EditDownloadItem(QString fileId, int recvSize, int state);
|
||||
|
||||
public slots:
|
||||
void handleDownloadsMenu(const QPoint &pos );
|
||||
};
|
||||
|
||||
#endif //ADAPTIXCLIENT_DOWNLOADSWIDGET_H
|
||||
@@ -7,9 +7,9 @@
|
||||
|
||||
class ListenersWidget : public QWidget
|
||||
{
|
||||
QWidget* mainWidget = nullptr;
|
||||
QGridLayout* mainGridLayout = nullptr;
|
||||
QTableWidget* tableWidget = nullptr;
|
||||
QWidget* mainWidget = nullptr;
|
||||
QGridLayout* mainGridLayout = nullptr;
|
||||
QTableWidget* tableWidget = nullptr;
|
||||
|
||||
void createUI();
|
||||
|
||||
|
||||
@@ -19,4 +19,6 @@ QString FormatSecToStr(int seconds);
|
||||
|
||||
QString TrimmedEnds(QString str);
|
||||
|
||||
QString BytesToFormat(int bytes);
|
||||
|
||||
#endif //ADAPTIXCLIENT_CONVERT_H
|
||||
@@ -67,8 +67,18 @@
|
||||
#define TYPE_AGENT_TASK_UPDATE 0x45
|
||||
#define TYPE_AGENT_CONSOLE_OUT 0x46
|
||||
|
||||
#define TYPE_DOWNLOAD_CREATE 0x51
|
||||
#define TYPE_DOWNLOAD_UPDATE 0x52
|
||||
|
||||
//////////
|
||||
|
||||
#define DOWNLOAD_STATE_RUNNING 0x1
|
||||
#define DOWNLOAD_STATE_STOPPED 0x2
|
||||
#define DOWNLOAD_STATE_FINISHED 0x3
|
||||
#define DOWNLOAD_STATE_CANCELED 0x4
|
||||
|
||||
/////////
|
||||
|
||||
#define COLOR_NeonGreen "#39FF14" // green
|
||||
#define COLOR_Berry "#A01641" // red
|
||||
#define COLOR_ChiliPepper "#E32227" // red
|
||||
@@ -119,4 +129,17 @@ typedef struct AgentData
|
||||
int LastTick;
|
||||
} AgentData;
|
||||
|
||||
typedef struct DownloadData
|
||||
{
|
||||
QString FileId;
|
||||
QString AgentId;
|
||||
QString AgentName;
|
||||
QString Computer;
|
||||
QString Filename;
|
||||
int TotalSize;
|
||||
int RecvSize;
|
||||
int State;
|
||||
QString Date;
|
||||
} DownloadData;
|
||||
|
||||
#endif //ADAPTIXCLIENT_MAIN_H
|
||||
|
||||
@@ -251,6 +251,43 @@ bool AdaptixWidget::isValidSyncPacket(QJsonObject jsonObj)
|
||||
return true;
|
||||
}
|
||||
|
||||
if(spType == TYPE_DOWNLOAD_CREATE ) {
|
||||
if (!jsonObj.contains("d_agent_id") || !jsonObj["d_agent_id"].isString()) {
|
||||
return false;
|
||||
}
|
||||
if (!jsonObj.contains("d_file_id") || !jsonObj["d_file_id"].isString()) {
|
||||
return false;
|
||||
}
|
||||
if (!jsonObj.contains("d_agent_name") || !jsonObj["d_agent_name"].isString()) {
|
||||
return false;
|
||||
}
|
||||
if (!jsonObj.contains("d_computer") || !jsonObj["d_computer"].isString()) {
|
||||
return false;
|
||||
}
|
||||
if (!jsonObj.contains("d_file") || !jsonObj["d_file"].isString()) {
|
||||
return false;
|
||||
}
|
||||
if (!jsonObj.contains("d_size") || !jsonObj["d_size"].isDouble()) {
|
||||
return false;
|
||||
}
|
||||
if (!jsonObj.contains("d_date") || !jsonObj["d_date"].isDouble()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if(spType == TYPE_DOWNLOAD_UPDATE ) {
|
||||
if (!jsonObj.contains("d_file_id") || !jsonObj["d_file_id"].isString()) {
|
||||
return false;
|
||||
}
|
||||
if (!jsonObj.contains("d_recv_size") || !jsonObj["d_recv_size"].isDouble()) {
|
||||
return false;
|
||||
}
|
||||
if (!jsonObj.contains("d_state") || !jsonObj["d_state"].isDouble()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -450,4 +487,31 @@ void AdaptixWidget::processSyncPacket(QJsonObject jsonObj)
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(spType == TYPE_DOWNLOAD_CREATE )
|
||||
{
|
||||
DownloadData newDownload = {0};
|
||||
newDownload.AgentId = jsonObj["d_agent_id"].toString();
|
||||
newDownload.FileId = jsonObj["d_file_id"].toString();
|
||||
newDownload.AgentName = jsonObj["d_agent_name"].toString();
|
||||
newDownload.Computer = jsonObj["d_computer"].toString();
|
||||
newDownload.Filename = jsonObj["d_file"].toString();
|
||||
newDownload.TotalSize = jsonObj["d_size"].toDouble();
|
||||
newDownload.Date = UnixTimestampGlobalToStringLocal(static_cast<qint64>(jsonObj["d_date"].toDouble()));
|
||||
newDownload.RecvSize = 0;
|
||||
newDownload.State = DOWNLOAD_STATE_RUNNING;
|
||||
|
||||
DownloadsTab->AddDownloadItem(newDownload);
|
||||
|
||||
return;
|
||||
}
|
||||
if(spType == TYPE_DOWNLOAD_UPDATE ) {
|
||||
QString fileId = jsonObj["d_file_id"].toString();
|
||||
int recvSize = jsonObj["d_recv_size"].toDouble();
|
||||
int state = jsonObj["d_state"].toDouble();
|
||||
|
||||
DownloadsTab->EditDownloadItem(fileId, recvSize, state);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ AdaptixWidget::AdaptixWidget(AuthProfile authProfile)
|
||||
LogsTab = new LogsWidget();
|
||||
ListenersTab = new ListenersWidget(this);
|
||||
SessionsTablePage = new SessionsTableWidget(this);
|
||||
DownloadsTab = new DownloadsWidget(this);
|
||||
|
||||
mainStackedWidget->addWidget(SessionsTablePage);
|
||||
mainStackedWidget->setCurrentIndex(0);
|
||||
@@ -26,6 +27,7 @@ AdaptixWidget::AdaptixWidget(AuthProfile authProfile)
|
||||
connect( mainTabWidget->tabBar(), &QTabBar::tabCloseRequested, this, &AdaptixWidget::RemoveTab );
|
||||
connect( logsButton, &QPushButton::clicked, this, &AdaptixWidget::LoadLogsUI);
|
||||
connect( listenersButton, &QPushButton::clicked, this, &AdaptixWidget::LoadListenersUI);
|
||||
connect( downloadsButton, &QPushButton::clicked, this, &AdaptixWidget::LoadDownloadsUI);
|
||||
|
||||
connect( TickThread, &QThread::started, TickWorker, &LastTickWorker::run );
|
||||
|
||||
@@ -42,8 +44,6 @@ AdaptixWidget::AdaptixWidget(AuthProfile authProfile)
|
||||
line_2->setVisible(false);
|
||||
jobsButton->setVisible(false);
|
||||
proxyButton->setVisible(false);
|
||||
line_3->setVisible(false);
|
||||
downloadsButton->setVisible(false);
|
||||
credsButton->setVisible(false);
|
||||
screensButton->setVisible(false);
|
||||
keysButton->setVisible(false);
|
||||
@@ -242,6 +242,12 @@ void AdaptixWidget::LoadListenersUI()
|
||||
this->AddTab(ListenersTab, "Listeners", ":/icons/listeners");
|
||||
}
|
||||
|
||||
void AdaptixWidget::LoadDownloadsUI()
|
||||
{
|
||||
this->AddTab(DownloadsTab, "Downloads", ":/icons/downloads");
|
||||
}
|
||||
|
||||
|
||||
void AdaptixWidget::LoadConsoleUI(QString AgentId)
|
||||
{
|
||||
if( !Agents.contains(AgentId) )
|
||||
@@ -251,7 +257,6 @@ void AdaptixWidget::LoadConsoleUI(QString AgentId)
|
||||
this->AddTab(Agents[AgentId]->Console, text);
|
||||
}
|
||||
|
||||
|
||||
void AdaptixWidget::ChannelClose()
|
||||
{
|
||||
LogInfo("WebSocker closed");
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
#include <UI/Widgets/DownloadsWidget.h>
|
||||
#include <UI/Widgets/AdaptixWidget.h>
|
||||
|
||||
DownloadsWidget::DownloadsWidget(QWidget* w)
|
||||
{
|
||||
this->mainWidget = w;
|
||||
this->createUI();
|
||||
|
||||
connect( tableWidget, &QTableWidget::customContextMenuRequested, this, &DownloadsWidget::handleDownloadsMenu );
|
||||
}
|
||||
|
||||
void DownloadsWidget::createUI()
|
||||
{
|
||||
tableWidget = new QTableWidget(this );
|
||||
tableWidget->setColumnCount(9 );
|
||||
tableWidget->setContextMenuPolicy( Qt::CustomContextMenu );
|
||||
tableWidget->setAutoFillBackground( false );
|
||||
tableWidget->setShowGrid( false );
|
||||
tableWidget->setSortingEnabled( true );
|
||||
tableWidget->setWordWrap( true );
|
||||
tableWidget->setCornerButtonEnabled( true ); // true
|
||||
tableWidget->setSelectionBehavior( QAbstractItemView::SelectRows );
|
||||
tableWidget->setFocusPolicy( Qt::NoFocus );
|
||||
tableWidget->setAlternatingRowColors( true );
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
|
||||
tableWidget->horizontalHeader()->setCascadingSectionResizes( true );
|
||||
tableWidget->horizontalHeader()->setHighlightSections( false );
|
||||
tableWidget->verticalHeader()->setVisible( false );
|
||||
|
||||
tableWidget->setHorizontalHeaderItem( 0, new QTableWidgetItem( "File ID" ) );
|
||||
tableWidget->setHorizontalHeaderItem( 1, new QTableWidgetItem( "Agent Type" ) );
|
||||
tableWidget->setHorizontalHeaderItem( 2, new QTableWidgetItem( "Agent ID" ) );
|
||||
tableWidget->setHorizontalHeaderItem( 3, new QTableWidgetItem( "Computer" ) );
|
||||
tableWidget->setHorizontalHeaderItem( 4, new QTableWidgetItem( "File" ) );
|
||||
tableWidget->setHorizontalHeaderItem( 5, new QTableWidgetItem( "Date" ) );
|
||||
tableWidget->setHorizontalHeaderItem( 6, new QTableWidgetItem( "Size" ) );
|
||||
tableWidget->setHorizontalHeaderItem( 7, new QTableWidgetItem( "Received" ) );
|
||||
tableWidget->setHorizontalHeaderItem( 8, new QTableWidgetItem( "Progress" ) );
|
||||
tableWidget->hideColumn( 0 );
|
||||
|
||||
mainGridLayout = new QGridLayout(this );
|
||||
mainGridLayout->setContentsMargins(0, 0, 0, 0 );
|
||||
mainGridLayout->addWidget(tableWidget, 0, 0, 1, 4 );
|
||||
}
|
||||
|
||||
DownloadsWidget::~DownloadsWidget() = default;
|
||||
|
||||
void DownloadsWidget::AddDownloadItem(DownloadData newDownload )
|
||||
{
|
||||
auto adaptixWidget = qobject_cast<AdaptixWidget*>( mainWidget );
|
||||
if(adaptixWidget->Downloads.contains(newDownload.FileId))
|
||||
return;
|
||||
|
||||
auto item_FileID = new QTableWidgetItem( newDownload.FileId );
|
||||
auto item_AgentName = new QTableWidgetItem( newDownload.AgentName );
|
||||
auto item_AgentID = new QTableWidgetItem( newDownload.AgentId );
|
||||
auto item_Computer = new QTableWidgetItem( newDownload.Computer );
|
||||
auto item_File = new QTableWidgetItem( newDownload.Filename );
|
||||
auto item_Date = new QTableWidgetItem( newDownload.Date );
|
||||
auto item_Size = new QTableWidgetItem( BytesToFormat(newDownload.TotalSize) );
|
||||
auto item_Received = new QTableWidgetItem( BytesToFormat(newDownload.RecvSize) );
|
||||
|
||||
item_FileID->setTextAlignment( Qt::AlignCenter );
|
||||
item_FileID->setFlags( item_FileID->flags() ^ Qt::ItemIsEditable );
|
||||
|
||||
item_AgentName->setTextAlignment( Qt::AlignCenter );
|
||||
item_AgentName->setFlags( item_AgentName->flags() ^ Qt::ItemIsEditable );
|
||||
|
||||
item_AgentID->setTextAlignment( Qt::AlignCenter );
|
||||
item_AgentID->setFlags( item_AgentID->flags() ^ Qt::ItemIsEditable );
|
||||
|
||||
item_Computer->setTextAlignment( Qt::AlignCenter );
|
||||
item_Computer->setFlags( item_Computer->flags() ^ Qt::ItemIsEditable );
|
||||
|
||||
item_File->setTextAlignment( Qt::AlignCenter );
|
||||
item_File->setFlags( item_File->flags() ^ Qt::ItemIsEditable );
|
||||
item_File->setToolTip(item_File->text());
|
||||
|
||||
item_Date->setTextAlignment( Qt::AlignCenter );
|
||||
item_Date->setFlags( item_Date->flags() ^ Qt::ItemIsEditable );
|
||||
|
||||
item_Size->setTextAlignment( Qt::AlignCenter );
|
||||
item_Size->setFlags( item_Size->flags() ^ Qt::ItemIsEditable );
|
||||
|
||||
item_Received->setTextAlignment( Qt::AlignCenter );
|
||||
item_Received->setFlags( item_Received->flags() ^ Qt::ItemIsEditable );
|
||||
|
||||
QProgressBar *pgbar = new QProgressBar();
|
||||
pgbar->setMinimum(0);
|
||||
pgbar->setMaximum(newDownload.TotalSize);
|
||||
pgbar->setValue(newDownload.RecvSize);
|
||||
pgbar->setMinimumSize(QSize(200,24));
|
||||
pgbar->setMaximumSize(QSize(200,24));
|
||||
|
||||
if( tableWidget->rowCount() < 1 )
|
||||
tableWidget->setRowCount( 1 );
|
||||
else
|
||||
tableWidget->setRowCount( tableWidget->rowCount() + 1 );
|
||||
|
||||
bool isSortingEnabled = tableWidget->isSortingEnabled();
|
||||
tableWidget->setSortingEnabled( false );
|
||||
tableWidget->setItem( tableWidget->rowCount() - 1, 0, item_FileID );
|
||||
tableWidget->setItem( tableWidget->rowCount() - 1, 1, item_AgentName );
|
||||
tableWidget->setItem( tableWidget->rowCount() - 1, 2, item_AgentID );
|
||||
tableWidget->setItem( tableWidget->rowCount() - 1, 3, item_Computer );
|
||||
tableWidget->setItem( tableWidget->rowCount() - 1, 4, item_File );
|
||||
tableWidget->setItem( tableWidget->rowCount() - 1, 5, item_Date );
|
||||
tableWidget->setItem( tableWidget->rowCount() - 1, 6, item_Size );
|
||||
tableWidget->setItem( tableWidget->rowCount() - 1, 7, item_Received );
|
||||
tableWidget->setCellWidget( tableWidget->rowCount() - 1, 8, pgbar );
|
||||
tableWidget->setSortingEnabled( isSortingEnabled );
|
||||
|
||||
if( newDownload.State == DOWNLOAD_STATE_STOPPED )
|
||||
pgbar->setEnabled(false);
|
||||
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode( 1, QHeaderView::ResizeToContents );
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode( 2, QHeaderView::ResizeToContents );
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode( 6, QHeaderView::ResizeToContents );
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode( 7, QHeaderView::ResizeToContents );
|
||||
tableWidget->horizontalHeader()->setSectionResizeMode( 8, QHeaderView::ResizeToContents );
|
||||
|
||||
adaptixWidget->Downloads[newDownload.FileId] = newDownload;
|
||||
}
|
||||
|
||||
void DownloadsWidget::EditDownloadItem(QString fileId, int recvSize, int state)
|
||||
{
|
||||
auto adaptixWidget = qobject_cast<AdaptixWidget*>( mainWidget );
|
||||
adaptixWidget->Downloads[fileId].RecvSize = recvSize;
|
||||
adaptixWidget->Downloads[fileId].State = state;
|
||||
|
||||
for (int row = 0; row < tableWidget->rowCount(); ++row) {
|
||||
QTableWidgetItem *item = tableWidget->item(row, 0);
|
||||
if ( item && item->text() == fileId ) {
|
||||
tableWidget->item(row, 7)->setText(BytesToFormat(recvSize) );
|
||||
|
||||
QProgressBar *pgbar = (QProgressBar*) tableWidget->cellWidget(row,8);
|
||||
pgbar->setValue(recvSize);
|
||||
|
||||
if( state == DOWNLOAD_STATE_STOPPED) {
|
||||
pgbar->setEnabled(false);
|
||||
}
|
||||
else if(state == DOWNLOAD_STATE_RUNNING) {
|
||||
pgbar->setEnabled(true);
|
||||
}
|
||||
else if (state == DOWNLOAD_STATE_FINISHED) {
|
||||
adaptixWidget->Downloads[fileId].RecvSize = adaptixWidget->Downloads[fileId].TotalSize;
|
||||
|
||||
tableWidget->item( row, 7 )->setText("");
|
||||
|
||||
auto item_Status = new QTableWidgetItem( "Finished" );
|
||||
item_Status->setTextAlignment( Qt::AlignCenter );
|
||||
tableWidget->removeCellWidget(row,8);
|
||||
tableWidget->setItem( row, 8, item_Status );
|
||||
tableWidget->item( row, 8 )->setForeground(QColor(COLOR_NeonGreen));
|
||||
}
|
||||
else if (state == DOWNLOAD_STATE_CANCELED) {
|
||||
tableWidget->removeCellWidget(row,8);
|
||||
tableWidget->removeRow( row );
|
||||
adaptixWidget->Downloads.remove(fileId);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadsWidget::handleDownloadsMenu(const QPoint &pos )
|
||||
{
|
||||
if ( ! tableWidget->itemAt( pos ) )
|
||||
return;
|
||||
|
||||
auto FileID = tableWidget->item( tableWidget->currentRow(), 0 )->text();
|
||||
auto Received = tableWidget->item( tableWidget->currentRow(), 7 )->text();
|
||||
|
||||
auto MenuFile = QMenu();
|
||||
if(Received.compare("") == 0) {
|
||||
MenuFile.addAction( "Sync file to client" );
|
||||
MenuFile.addAction( "Delete file" );
|
||||
}
|
||||
else {
|
||||
if( tableWidget->cellWidget( tableWidget->currentRow(), 8)->isEnabled() )
|
||||
MenuFile.addAction( "Stop" );
|
||||
else
|
||||
MenuFile.addAction( "Start" );
|
||||
MenuFile.addAction( "Cancel" );
|
||||
}
|
||||
|
||||
auto *action = MenuFile.exec( tableWidget->horizontalHeader()->viewport()->mapToGlobal( pos ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -68,4 +68,20 @@ QString FormatSecToStr(int seconds)
|
||||
QString TrimmedEnds(QString str)
|
||||
{
|
||||
return str.remove(QRegularExpression("\\s+$"));
|
||||
}
|
||||
}
|
||||
|
||||
QString BytesToFormat(int bytes)
|
||||
{
|
||||
const double KB = 1024.0;
|
||||
const double MB = KB * 1024;
|
||||
const double GB = MB * 1024;
|
||||
|
||||
if (bytes >= GB) {
|
||||
return QString::number(bytes / GB, 'f', 2) + " Gb";
|
||||
} else if (bytes >= MB) {
|
||||
return QString::number(bytes / MB, 'f', 2) + " Mb";
|
||||
} else {
|
||||
return QString::number(bytes / KB, 'f', 2) + " Kb";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user