new Welcome Page and firstrunWizard (#235)
Co-authored-by: Chris Rizzitello <crizzitello@ics.com>main
parent
3e1ba34ca5
commit
26fb82edd5
|
@ -64,6 +64,7 @@ find_package(Qt6 6.5.0 REQUIRED COMPONENTS
|
||||||
Network
|
Network
|
||||||
Sql
|
Sql
|
||||||
Core
|
Core
|
||||||
|
Svg
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(deploy)
|
add_subdirectory(deploy)
|
||||||
|
|
|
@ -104,6 +104,9 @@ QString AppConfig::defaultValue(const QString &key)
|
||||||
if (key == CONFIG::APIURL)
|
if (key == CONFIG::APIURL)
|
||||||
return QStringLiteral("http://localhost:8080");
|
return QStringLiteral("http://localhost:8080");
|
||||||
|
|
||||||
|
if (key == CONFIG::SHOW_WELCOME_SCREEN)
|
||||||
|
return QStringLiteral("true");
|
||||||
|
|
||||||
if (key == CONFIG::SHORTCUT_CAPTURECLIPBOARD) {
|
if (key == CONFIG::SHORTCUT_CAPTURECLIPBOARD) {
|
||||||
if(!get()->appSettings->value(key).isValid())
|
if(!get()->appSettings->value(key).isValid())
|
||||||
return QStringLiteral("Meta+Alt+v");
|
return QStringLiteral("Meta+Alt+v");
|
||||||
|
|
|
@ -21,6 +21,7 @@ struct CONFIG {
|
||||||
inline static const auto COMMAND_CAPTUREWINDOW = QStringLiteral("captureWindowExec");
|
inline static const auto COMMAND_CAPTUREWINDOW = QStringLiteral("captureWindowExec");
|
||||||
inline static const auto SHORTCUT_CAPTUREWINDOW = QStringLiteral("captureWindowShortcut");
|
inline static const auto SHORTCUT_CAPTUREWINDOW = QStringLiteral("captureWindowShortcut");
|
||||||
inline static const auto SHORTCUT_CAPTURECLIPBOARD = QStringLiteral("captureClipboardShortcut");
|
inline static const auto SHORTCUT_CAPTURECLIPBOARD = QStringLiteral("captureClipboardShortcut");
|
||||||
|
inline static const auto SHOW_WELCOME_SCREEN = QStringLiteral("showWelcomeScreen");
|
||||||
};
|
};
|
||||||
|
|
||||||
/// AppConfig is a singleton for accessing the application's configuration.
|
/// AppConfig is a singleton for accessing the application's configuration.
|
||||||
|
@ -102,5 +103,6 @@ private:
|
||||||
CONFIG::COMMAND_CAPTUREWINDOW,
|
CONFIG::COMMAND_CAPTUREWINDOW,
|
||||||
CONFIG::SHORTCUT_CAPTUREWINDOW,
|
CONFIG::SHORTCUT_CAPTUREWINDOW,
|
||||||
CONFIG::SHORTCUT_CAPTURECLIPBOARD,
|
CONFIG::SHORTCUT_CAPTURECLIPBOARD,
|
||||||
|
CONFIG::SHOW_WELCOME_SCREEN,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,6 +9,19 @@ add_library (FORMS STATIC
|
||||||
getinfo/getinfo.cpp getinfo/getinfo.h
|
getinfo/getinfo.cpp getinfo/getinfo.h
|
||||||
porting/porting_dialog.cpp porting/porting_dialog.h
|
porting/porting_dialog.cpp porting/porting_dialog.h
|
||||||
settings/settings.cpp settings/settings.h
|
settings/settings.cpp settings/settings.h
|
||||||
|
firstRunWizard/firstTimeWizard.h firstRunWizard/firstTimeWizard.cpp
|
||||||
|
firstRunWizard/welcomepage.h firstRunWizard/welcomepage.cpp
|
||||||
|
firstRunWizard/wizardpage.h firstRunWizard/wizardpage.cpp
|
||||||
|
firstRunWizard/requirementspage.h firstRunWizard/requirementspage.cpp
|
||||||
|
firstRunWizard/evidencepage.h firstRunWizard/evidencepage.cpp
|
||||||
|
firstRunWizard/apikeyspage.h firstRunWizard/apikeyspage.cpp
|
||||||
|
firstRunWizard/hostpathpage.h firstRunWizard/hostpathpage.cpp
|
||||||
|
firstRunWizard/hosttestpage.h firstRunWizard/hosttestpage.cpp
|
||||||
|
firstRunWizard/captureareapage.h firstRunWizard/captureareapage.cpp
|
||||||
|
firstRunWizard/capturewindowpage.h firstRunWizard/capturewindowpage.cpp
|
||||||
|
firstRunWizard/captureclipboardpage.h firstRunWizard/captureclipboardpage.cpp
|
||||||
|
firstRunWizard/opspage.h firstRunWizard/opspage.cpp
|
||||||
|
firstRunWizard/finishedpage.h firstRunWizard/finishedpage.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(ASHIRT::FORMS ALIAS FORMS)
|
add_library(ASHIRT::FORMS ALIAS FORMS)
|
||||||
|
@ -26,6 +39,7 @@ target_link_libraries ( FORMS
|
||||||
Qt::Gui
|
Qt::Gui
|
||||||
Qt::Widgets
|
Qt::Widgets
|
||||||
Qt::Sql
|
Qt::Sql
|
||||||
|
Qt::Svg
|
||||||
ASHIRT::HELPERS
|
ASHIRT::HELPERS
|
||||||
ASHIRT::MODELS
|
ASHIRT::MODELS
|
||||||
ASHIRT::COMPONENTS
|
ASHIRT::COMPONENTS
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
#include "apikeyspage.h"
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <appconfig.h>
|
||||||
|
|
||||||
|
bool ApiKeysPage::validatePage()
|
||||||
|
{
|
||||||
|
if (!field("host.accessKey").isValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!field("host.secretKey").isValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ApiKeysPage::initializePage()
|
||||||
|
{
|
||||||
|
QString accessKey = AppConfig::value(CONFIG::ACCESSKEY);
|
||||||
|
setField("host.accessKey", accessKey);
|
||||||
|
accessKeyLine->setText(accessKey);
|
||||||
|
|
||||||
|
QString secretKey = AppConfig::value(CONFIG::SECRETKEY);
|
||||||
|
setField("host.secretKey", secretKey);
|
||||||
|
secretKeyLine->setText(secretKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
ApiKeysPage::ApiKeysPage(QWidget *parent)
|
||||||
|
: WizardPage{Page_Api, parent}
|
||||||
|
{
|
||||||
|
|
||||||
|
auto f = font();
|
||||||
|
auto _lblTitleLabel = new QLabel(this);
|
||||||
|
f.setPointSize(titleFont.first);
|
||||||
|
f.setWeight(titleFont.second);
|
||||||
|
_lblTitleLabel->setFont(f);
|
||||||
|
_lblTitleLabel->setText(tr("API Keys"));
|
||||||
|
|
||||||
|
auto _lblSubtitle = new QLabel(this);
|
||||||
|
f.setPointSize(subTitleFont.first);
|
||||||
|
f.setWeight(subTitleFont.second);
|
||||||
|
_lblSubtitle->setFont(f);
|
||||||
|
_lblSubtitle->setWordWrap(true);
|
||||||
|
_lblSubtitle->setText(tr("Input Api keys for the server"));
|
||||||
|
|
||||||
|
auto _lblBody = new QLabel(this);
|
||||||
|
f.setPointSize(bodyFont.first);
|
||||||
|
f.setWeight(bodyFont.second);
|
||||||
|
_lblBody->setFont(f);
|
||||||
|
_lblBody->setWordWrap(true);
|
||||||
|
_lblBody->setText(tr("• Login to the Ashirt server click the profile icon in the top right then select <i>Account Settings</i><br>"));
|
||||||
|
|
||||||
|
auto _lblBody2 = new QLabel(this);
|
||||||
|
_lblBody2->setFont(f);
|
||||||
|
_lblBody2->setWordWrap(true);
|
||||||
|
_lblBody2->setText(tr("• Select <i>API Keys</i> on the left, select click <i>Generate New API Key</i><br>"));
|
||||||
|
|
||||||
|
auto _lblBody3 = new QLabel(this);
|
||||||
|
_lblBody3->setFont(f);
|
||||||
|
_lblBody3->setWordWrap(true);
|
||||||
|
_lblBody3->setText(tr("• Enter your keys below"));
|
||||||
|
|
||||||
|
auto _lblAKey = new QLabel(this);
|
||||||
|
f.setPointSize(smallFont.first);
|
||||||
|
f.setWeight(smallFont.second);
|
||||||
|
_lblAKey->setFont(f);
|
||||||
|
_lblAKey->setText(tr("Access Key"));
|
||||||
|
|
||||||
|
accessKeyLine = new QLineEdit(this);
|
||||||
|
accessKeyLine->setMaxLength(24);
|
||||||
|
accessKeyLine->setTextMargins(3,0,3,0);
|
||||||
|
accessKeyLine->setMaximumWidth(fontMetrics().averageCharWidth() * 27);
|
||||||
|
registerField("host.accessKey*", accessKeyLine);
|
||||||
|
|
||||||
|
auto t1 = new QVBoxLayout();
|
||||||
|
t1->setSpacing(1);
|
||||||
|
t1->addWidget(_lblAKey);
|
||||||
|
t1->addWidget(accessKeyLine);
|
||||||
|
|
||||||
|
auto _lblBKey = new QLabel(this);
|
||||||
|
f.setPointSize(smallFont.first);
|
||||||
|
f.setWeight(smallFont.second);
|
||||||
|
_lblBKey->setFont(f);
|
||||||
|
_lblBKey->setText(tr("Secret Key"));
|
||||||
|
|
||||||
|
secretKeyLine = new QLineEdit(this);
|
||||||
|
secretKeyLine->setTextMargins(3,0,3,0);
|
||||||
|
registerField("host.secretKey*", secretKeyLine);
|
||||||
|
|
||||||
|
auto t2 = new QVBoxLayout();
|
||||||
|
t2->setSpacing(1);
|
||||||
|
t2->addWidget(_lblBKey);
|
||||||
|
t2->addWidget(secretKeyLine);
|
||||||
|
|
||||||
|
auto tLayout = new QHBoxLayout();
|
||||||
|
tLayout->addLayout(t1);
|
||||||
|
tLayout->addLayout(t2);
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout();
|
||||||
|
layout->addWidget(_lblTitleLabel);
|
||||||
|
layout->addWidget(_lblSubtitle);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,30,QSizePolicy::Minimum, QSizePolicy::Fixed));
|
||||||
|
layout->addWidget(_lblBody);
|
||||||
|
layout->addWidget(_lblBody2);
|
||||||
|
layout->addWidget(_lblBody3);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,30,QSizePolicy::Minimum, QSizePolicy::Fixed));
|
||||||
|
layout->addLayout(tLayout);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Minimum, QSizePolicy::Expanding));
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wizardpage.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QLineEdit;
|
||||||
|
class ApiKeysPage : public WizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
bool validatePage() override;
|
||||||
|
void initializePage() override;
|
||||||
|
ApiKeysPage(QWidget *parent = nullptr);
|
||||||
|
private:
|
||||||
|
QLineEdit * accessKeyLine = nullptr;
|
||||||
|
QLineEdit * secretKeyLine = nullptr;
|
||||||
|
};
|
|
@ -0,0 +1,115 @@
|
||||||
|
#include "captureareapage.h"
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <appconfig.h>
|
||||||
|
|
||||||
|
#include "hotkeymanager.h"
|
||||||
|
#include "components/custom_keyseq_edit/singlestrokekeysequenceedit.h"
|
||||||
|
|
||||||
|
bool CaptureAreaPage::validatePage()
|
||||||
|
{
|
||||||
|
if(!field("command.area").isValid())
|
||||||
|
return false;
|
||||||
|
AppConfig::setValue(CONFIG::COMMAND_SCREENSHOT, field("command.area").toString());
|
||||||
|
|
||||||
|
if(!field("keySequence.area").isValid())
|
||||||
|
return false;
|
||||||
|
auto keyCombo = QKeySequence::fromString(field("keySequence.area").toString(), QKeySequence::NativeText);
|
||||||
|
AppConfig::setValue(CONFIG::SHORTCUT_SCREENSHOT, keyCombo.toString(QKeySequence::PortableText));
|
||||||
|
HotkeyManager::updateHotkeys();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaptureAreaPage::initializePage()
|
||||||
|
{
|
||||||
|
HotkeyManager::unregisterKey(HotkeyManager::ACTION_CAPTURE_AREA);
|
||||||
|
QString captureAreaCommand = AppConfig::value(CONFIG::COMMAND_SCREENSHOT);
|
||||||
|
if(!captureAreaCommand.isEmpty()) {
|
||||||
|
setField("command.area", captureAreaCommand);
|
||||||
|
captureAreaLine->setText(captureAreaCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString sequence = AppConfig::value(CONFIG::SHORTCUT_SCREENSHOT);
|
||||||
|
if(!sequence.isEmpty()) {
|
||||||
|
setField("keySequence.area", sequence);
|
||||||
|
captureAreaKeySequenceEdit->setKeySequence(QKeySequence::fromString(sequence));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaptureAreaPage::cleanupPage()
|
||||||
|
{
|
||||||
|
HotkeyManager::updateHotkeys();
|
||||||
|
}
|
||||||
|
|
||||||
|
CaptureAreaPage::CaptureAreaPage(QWidget *parent)
|
||||||
|
: WizardPage{Page_CaptureArea, parent}
|
||||||
|
{
|
||||||
|
auto f = font();
|
||||||
|
auto _lblTitleLabel = new QLabel(this);
|
||||||
|
f.setPointSize(titleFont.first);
|
||||||
|
f.setWeight(titleFont.second);
|
||||||
|
_lblTitleLabel->setFont(f);
|
||||||
|
_lblTitleLabel->setText(tr("Capture Area"));
|
||||||
|
|
||||||
|
auto _lblSubtitle = new QLabel(this);
|
||||||
|
f.setPointSize(subTitleFont.first);
|
||||||
|
f.setWeight(subTitleFont.second);
|
||||||
|
_lblSubtitle->setFont(f);
|
||||||
|
_lblSubtitle->setWordWrap(true);
|
||||||
|
_lblSubtitle->setText(tr("Set the capture area command and shortcut."));
|
||||||
|
|
||||||
|
auto _lblB1 = new QLabel(this);
|
||||||
|
f.setPointSize(bodyFont.first);
|
||||||
|
f.setWeight(bodyFont.second);
|
||||||
|
_lblB1->setFont(f);
|
||||||
|
_lblB1->setText(tr("<html><br><br>• Enter the command ashirt will use to capture area screenshots<br><br>• Enter a key combination that will trigger the capture area command<html>"));
|
||||||
|
|
||||||
|
auto hLayout = new QHBoxLayout();
|
||||||
|
hLayout->addWidget(_lblB1, 0, Qt::AlignHCenter);
|
||||||
|
|
||||||
|
auto _lblAKey = new QLabel(this);
|
||||||
|
f.setPointSize(smallFont.first);
|
||||||
|
f.setWeight(smallFont.second);
|
||||||
|
_lblAKey->setFont(f);
|
||||||
|
_lblAKey->setText(tr("Capture Area Command"));
|
||||||
|
|
||||||
|
captureAreaLine = new QLineEdit(this);
|
||||||
|
captureAreaLine->setTextMargins(3,0,3,0);
|
||||||
|
registerField("command.area*", captureAreaLine);
|
||||||
|
|
||||||
|
auto t1 = new QVBoxLayout();
|
||||||
|
t1->setSpacing(1);
|
||||||
|
t1->addWidget(_lblAKey);
|
||||||
|
t1->addWidget(captureAreaLine);
|
||||||
|
|
||||||
|
auto _lblBKey = new QLabel(this);
|
||||||
|
f.setPointSize(smallFont.first);
|
||||||
|
f.setWeight(smallFont.second);
|
||||||
|
_lblBKey->setFont(f);
|
||||||
|
_lblBKey->setText(tr("Shortcut"));
|
||||||
|
|
||||||
|
captureAreaKeySequenceEdit = new SingleStrokeKeySequenceEdit(this);
|
||||||
|
registerField("keySequence.area*", captureAreaKeySequenceEdit, "keySequence", SIGNAL(keySequenceChanged(const QKeySequence &)));
|
||||||
|
|
||||||
|
auto t2 = new QVBoxLayout();
|
||||||
|
t2->setSpacing(1);
|
||||||
|
t2->addWidget(_lblBKey);
|
||||||
|
t2->addWidget(captureAreaKeySequenceEdit);
|
||||||
|
|
||||||
|
auto tLayout = new QHBoxLayout();
|
||||||
|
tLayout->addLayout(t1, 8);
|
||||||
|
tLayout->addLayout(t2, 2);
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout();
|
||||||
|
layout->addWidget(_lblTitleLabel);
|
||||||
|
layout->addWidget(_lblSubtitle);
|
||||||
|
layout->addLayout(hLayout);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,60,QSizePolicy::Minimum, QSizePolicy::Fixed));
|
||||||
|
layout->addLayout(tLayout);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Minimum, QSizePolicy::Expanding));
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wizardpage.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QLineEdit;
|
||||||
|
class SingleStrokeKeySequenceEdit;
|
||||||
|
class CaptureAreaPage : public WizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
bool validatePage() override;
|
||||||
|
void initializePage() override;
|
||||||
|
void cleanupPage() override;
|
||||||
|
CaptureAreaPage(QWidget *parent = nullptr);
|
||||||
|
private:
|
||||||
|
QLineEdit *captureAreaLine = nullptr;
|
||||||
|
SingleStrokeKeySequenceEdit *captureAreaKeySequenceEdit = nullptr;
|
||||||
|
};
|
|
@ -0,0 +1,84 @@
|
||||||
|
#include "captureclipboardpage.h"
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <appconfig.h>
|
||||||
|
|
||||||
|
#include "hotkeymanager.h"
|
||||||
|
#include "components/custom_keyseq_edit/singlestrokekeysequenceedit.h"
|
||||||
|
|
||||||
|
bool CaptureClipboardPage::validatePage()
|
||||||
|
{
|
||||||
|
if(!field("keySequence.clipboard").isValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto keyCombo = QKeySequence::fromString(field("keySequence.clipboard").toString(), QKeySequence::NativeText);
|
||||||
|
AppConfig::setValue(CONFIG::SHORTCUT_CAPTURECLIPBOARD, keyCombo.toString(QKeySequence::PortableText));
|
||||||
|
HotkeyManager::updateHotkeys();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaptureClipboardPage::initializePage()
|
||||||
|
{
|
||||||
|
HotkeyManager::unregisterKey(HotkeyManager::ACTION_CAPTURE_CLIPBOARD);
|
||||||
|
QString sequence = AppConfig::value(CONFIG::SHORTCUT_CAPTURECLIPBOARD);
|
||||||
|
setField("keySequence.clipboard", sequence);
|
||||||
|
captureClipboardKeySequence->setKeySequence(QKeySequence::fromString(sequence));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaptureClipboardPage::cleanupPage()
|
||||||
|
{
|
||||||
|
HotkeyManager::updateHotkeys();
|
||||||
|
HotkeyManager::unregisterKey(HotkeyManager::ACTION_CAPTURE_WINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
CaptureClipboardPage::CaptureClipboardPage(QWidget *parent)
|
||||||
|
: WizardPage{WizardPage::Page_CaptureClipboard, parent}
|
||||||
|
{
|
||||||
|
auto f = font();
|
||||||
|
auto _lblTitleLabel = new QLabel(this);
|
||||||
|
f.setPointSize(titleFont.first);
|
||||||
|
f.setWeight(titleFont.second);
|
||||||
|
_lblTitleLabel->setFont(f);
|
||||||
|
_lblTitleLabel->setText(tr("Capture Cliboard"));
|
||||||
|
|
||||||
|
auto _lblSubtitle = new QLabel(this);
|
||||||
|
f.setPointSize(subTitleFont.first);
|
||||||
|
f.setWeight(subTitleFont.second);
|
||||||
|
_lblSubtitle->setFont(f);
|
||||||
|
_lblSubtitle->setWordWrap(true);
|
||||||
|
_lblSubtitle->setText(tr("Uploads clipboard images or text to ashirt.\nText is uploaded as a code block"));
|
||||||
|
|
||||||
|
auto _lblB1 = new QLabel(this);
|
||||||
|
f.setPointSize(bodyFont.first);
|
||||||
|
f.setWeight(bodyFont.second);
|
||||||
|
_lblB1->setFont(f);
|
||||||
|
_lblB1->setText(tr("\n\n• Enter the shortcut code below"));
|
||||||
|
|
||||||
|
auto _lblBKey = new QLabel(this);
|
||||||
|
f.setPointSize(smallFont.first);
|
||||||
|
f.setWeight(smallFont.second);
|
||||||
|
_lblBKey->setFont(f);
|
||||||
|
_lblBKey->setText(tr("Capture Clipboard Shortcut"));
|
||||||
|
|
||||||
|
captureClipboardKeySequence = new SingleStrokeKeySequenceEdit(this);
|
||||||
|
captureClipboardKeySequence->setFixedWidth(120);
|
||||||
|
registerField("keySequence.clipboard*", captureClipboardKeySequence, "keySequence", SIGNAL(keySequenceChanged(const QKeySequence &)));
|
||||||
|
|
||||||
|
auto t2 = new QVBoxLayout();
|
||||||
|
t2->setSpacing(1);
|
||||||
|
t2->addWidget(_lblBKey);
|
||||||
|
t2->addWidget(captureClipboardKeySequence);
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout();
|
||||||
|
layout->addWidget(_lblTitleLabel);
|
||||||
|
layout->addWidget(_lblSubtitle);
|
||||||
|
layout->addWidget(_lblB1);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,60,QSizePolicy::Minimum, QSizePolicy::Fixed));
|
||||||
|
layout->addLayout(t2);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Minimum, QSizePolicy::Expanding));
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wizardpage.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class SingleStrokeKeySequenceEdit;
|
||||||
|
class CaptureClipboardPage : public WizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
bool validatePage() override;
|
||||||
|
void initializePage() override;
|
||||||
|
void cleanupPage() override;
|
||||||
|
CaptureClipboardPage(QWidget *parent = nullptr);
|
||||||
|
private:
|
||||||
|
SingleStrokeKeySequenceEdit *captureClipboardKeySequence = nullptr;
|
||||||
|
};
|
|
@ -0,0 +1,113 @@
|
||||||
|
#include "capturewindowpage.h"
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QKeySequenceEdit>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <appconfig.h>
|
||||||
|
|
||||||
|
#include "hotkeymanager.h"
|
||||||
|
#include "components/custom_keyseq_edit/singlestrokekeysequenceedit.h"
|
||||||
|
|
||||||
|
bool CaptureWindowPage::validatePage()
|
||||||
|
{
|
||||||
|
if(!field("command.window").isValid())
|
||||||
|
return false;
|
||||||
|
AppConfig::setValue(CONFIG::COMMAND_CAPTUREWINDOW, field("command.window").toString());
|
||||||
|
|
||||||
|
if(!field("keySequence.window").isValid())
|
||||||
|
return false;
|
||||||
|
auto keyCombo = QKeySequence::fromString(field("keySequence.window").toString(), QKeySequence::NativeText);
|
||||||
|
AppConfig::setValue(CONFIG::SHORTCUT_CAPTUREWINDOW, keyCombo.toString(QKeySequence::PortableText));
|
||||||
|
HotkeyManager::updateHotkeys();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaptureWindowPage::initializePage()
|
||||||
|
{
|
||||||
|
HotkeyManager::unregisterKey(HotkeyManager::ACTION_CAPTURE_WINDOW);
|
||||||
|
QString captureWindowCommand = AppConfig::value(CONFIG::COMMAND_CAPTUREWINDOW);
|
||||||
|
setField("command.window", captureWindowCommand);
|
||||||
|
captureWindowLine->setText(captureWindowCommand);
|
||||||
|
|
||||||
|
QString sequence = AppConfig::value(CONFIG::SHORTCUT_CAPTUREWINDOW);
|
||||||
|
setField("keySequence.window", sequence);
|
||||||
|
captureWindowKeySequence->setKeySequence(QKeySequence::fromString(sequence));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CaptureWindowPage::cleanupPage()
|
||||||
|
{
|
||||||
|
HotkeyManager::updateHotkeys();
|
||||||
|
HotkeyManager::unregisterKey(HotkeyManager::ACTION_CAPTURE_AREA);
|
||||||
|
}
|
||||||
|
|
||||||
|
CaptureWindowPage::CaptureWindowPage(QWidget *parent)
|
||||||
|
: WizardPage{Page_CaptureWindow, parent}
|
||||||
|
{
|
||||||
|
auto f = font();
|
||||||
|
auto _lblTitleLabel = new QLabel(this);
|
||||||
|
f.setPointSize(titleFont.first);
|
||||||
|
f.setWeight(titleFont.second);
|
||||||
|
_lblTitleLabel->setFont(f);
|
||||||
|
_lblTitleLabel->setText(tr("Capture Window"));
|
||||||
|
|
||||||
|
auto _lblSubtitle = new QLabel(this);
|
||||||
|
f.setPointSize(subTitleFont.first);
|
||||||
|
f.setWeight(subTitleFont.second);
|
||||||
|
_lblSubtitle->setFont(f);
|
||||||
|
_lblSubtitle->setWordWrap(true);
|
||||||
|
_lblSubtitle->setText(tr("Set the capture window command and shortcut."));
|
||||||
|
|
||||||
|
auto _lblB1 = new QLabel(this);
|
||||||
|
f.setPointSize(bodyFont.first);
|
||||||
|
f.setWeight(bodyFont.second);
|
||||||
|
_lblB1->setFont(f);
|
||||||
|
_lblB1->setText(tr("<html><br><br>• Enter the command ashirt will use to capture window screenshots<br><br>• Enter a key combination that will trigger the capture window command<html>"));
|
||||||
|
|
||||||
|
auto hLayout = new QHBoxLayout();
|
||||||
|
hLayout->addWidget(_lblB1, 0, Qt::AlignHCenter);
|
||||||
|
|
||||||
|
auto _lblAKey = new QLabel(this);
|
||||||
|
f.setPointSize(smallFont.first);
|
||||||
|
f.setWeight(smallFont.second);
|
||||||
|
_lblAKey->setFont(f);
|
||||||
|
_lblAKey->setText(tr("Capture Window Command"));
|
||||||
|
|
||||||
|
captureWindowLine = new QLineEdit(this);
|
||||||
|
captureWindowLine->setTextMargins(3,0,3,0);
|
||||||
|
registerField("command.window*", captureWindowLine);
|
||||||
|
|
||||||
|
auto t1 = new QVBoxLayout();
|
||||||
|
t1->setSpacing(1);
|
||||||
|
t1->addWidget(_lblAKey);
|
||||||
|
t1->addWidget(captureWindowLine);
|
||||||
|
|
||||||
|
auto _lblBKey = new QLabel(this);
|
||||||
|
f.setPointSize(smallFont.first);
|
||||||
|
f.setWeight(smallFont.second);
|
||||||
|
_lblBKey->setFont(f);
|
||||||
|
_lblBKey->setText(tr("Shortcut"));
|
||||||
|
|
||||||
|
captureWindowKeySequence = new SingleStrokeKeySequenceEdit(this);
|
||||||
|
registerField("keySequence.window*", captureWindowKeySequence, "keySequence", SIGNAL(keySequenceChanged(const QKeySequence &)));
|
||||||
|
|
||||||
|
auto t2 = new QVBoxLayout();
|
||||||
|
t2->setSpacing(1);
|
||||||
|
t2->addWidget(_lblBKey);
|
||||||
|
t2->addWidget(captureWindowKeySequence);
|
||||||
|
|
||||||
|
auto tLayout = new QHBoxLayout();
|
||||||
|
tLayout->addLayout(t1, 8);
|
||||||
|
tLayout->addLayout(t2, 2);
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout();
|
||||||
|
layout->addWidget(_lblTitleLabel);
|
||||||
|
layout->addWidget(_lblSubtitle);
|
||||||
|
layout->addLayout(hLayout);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,60,QSizePolicy::Minimum, QSizePolicy::Fixed));
|
||||||
|
layout->addLayout(tLayout);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Minimum, QSizePolicy::Expanding));
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wizardpage.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QLineEdit;
|
||||||
|
class SingleStrokeKeySequenceEdit;
|
||||||
|
class CaptureWindowPage : public WizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
bool validatePage() override;
|
||||||
|
void initializePage() override;
|
||||||
|
void cleanupPage() override;
|
||||||
|
CaptureWindowPage(QWidget *parent = nullptr);
|
||||||
|
private:
|
||||||
|
QLineEdit *captureWindowLine = nullptr;
|
||||||
|
SingleStrokeKeySequenceEdit *captureWindowKeySequence = nullptr;
|
||||||
|
};
|
|
@ -0,0 +1,121 @@
|
||||||
|
#include "evidencepage.h"
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <appconfig.h>
|
||||||
|
|
||||||
|
bool EvidencePage::validatePage()
|
||||||
|
{
|
||||||
|
QDir path = field("eRepo").toString();
|
||||||
|
|
||||||
|
if (!path.exists())
|
||||||
|
path.mkpath(path.absolutePath());
|
||||||
|
|
||||||
|
if(!path.exists()) {
|
||||||
|
errorLabel->setText(tr("can not use selected path"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
AppConfig::setValue(CONFIG::EVIDENCEREPO, path.absolutePath());
|
||||||
|
errorLabel->setText(QString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EvidencePage::initializePage()
|
||||||
|
{
|
||||||
|
QString repoPath = AppConfig::value(CONFIG::EVIDENCEREPO);
|
||||||
|
setField("eRepo", repoPath);
|
||||||
|
evidenceLine->setText(repoPath);
|
||||||
|
|
||||||
|
if(repoPath.isEmpty())
|
||||||
|
errorLabel->setText(tr("Enter a Path"));
|
||||||
|
QDir repo(repoPath);
|
||||||
|
|
||||||
|
if (!repo.exists()) {
|
||||||
|
repo.mkpath(repo.absolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!repo.exists() || !repo.isReadable())
|
||||||
|
errorLabel->setText(tr("Invalid Path"));
|
||||||
|
}
|
||||||
|
|
||||||
|
EvidencePage::EvidencePage(QWidget *parent)
|
||||||
|
: WizardPage{Page_Evidence, parent}
|
||||||
|
{
|
||||||
|
auto f = font();
|
||||||
|
|
||||||
|
auto _lblTitleLabel = new QLabel(this);
|
||||||
|
f.setPointSize(titleFont.first);
|
||||||
|
f.setWeight(titleFont.second);
|
||||||
|
_lblTitleLabel->setFont(f);
|
||||||
|
_lblTitleLabel->setText(tr("Evidence Repository"));
|
||||||
|
|
||||||
|
auto _lblSubtitle = new QLabel(this);
|
||||||
|
f.setPointSize(subTitleFont.first);
|
||||||
|
f.setWeight(subTitleFont.second);
|
||||||
|
_lblSubtitle->setFont(f);
|
||||||
|
_lblSubtitle->setWordWrap(true);
|
||||||
|
_lblSubtitle->setText(tr("This is where evidence is stored and your jumping off point.\n Files will be stored in a subdirectory using the operation name."));
|
||||||
|
|
||||||
|
auto _lblEvidence = new QLabel(this);
|
||||||
|
f.setPointSize(smallFont.first);
|
||||||
|
f.setWeight(smallFont.second);
|
||||||
|
_lblEvidence->setFont(f);
|
||||||
|
_lblEvidence->setText(tr("Evidence Repository:"));
|
||||||
|
|
||||||
|
evidenceLine = new QLineEdit(this);
|
||||||
|
evidenceLine->setTextMargins(3,0,3,0);
|
||||||
|
registerField("eRepo*", evidenceLine);
|
||||||
|
|
||||||
|
auto _btnRepoBrowse = new QPushButton(this);
|
||||||
|
_btnRepoBrowse->setText(tr("Browse"));
|
||||||
|
connect(_btnRepoBrowse, &QPushButton::clicked, this, [this] {
|
||||||
|
QString txt = QFileDialog::getExistingDirectory(this, tr("Select Path to Store Evidence"), evidenceLine->text());
|
||||||
|
if(txt.isEmpty())
|
||||||
|
return;
|
||||||
|
evidenceLine->setText(txt);
|
||||||
|
setField("eRepo", txt);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto _btnReset = new QPushButton(this);
|
||||||
|
_btnReset->setText(tr("Restore Default"));
|
||||||
|
connect(_btnReset, &QPushButton::clicked, this, [this] {
|
||||||
|
evidenceLine->setText(AppConfig::defaultValue(CONFIG::EVIDENCEREPO));
|
||||||
|
setField("eRepo", evidenceLine->text());
|
||||||
|
});
|
||||||
|
|
||||||
|
errorLabel = new QLabel(this);
|
||||||
|
f.setPointSize(smallFont.first);
|
||||||
|
f.setWeight(smallFont.second);
|
||||||
|
errorLabel->setFont(f);
|
||||||
|
|
||||||
|
auto btnLayout = new QHBoxLayout();
|
||||||
|
btnLayout->addWidget(evidenceLine);
|
||||||
|
btnLayout->addWidget(_btnRepoBrowse);
|
||||||
|
btnLayout->addWidget(_btnReset);
|
||||||
|
|
||||||
|
auto t1 = new QVBoxLayout();
|
||||||
|
t1->setSpacing(1);
|
||||||
|
t1->addWidget(_lblEvidence);
|
||||||
|
t1->addLayout(btnLayout);
|
||||||
|
t1->addWidget(errorLabel);
|
||||||
|
|
||||||
|
auto _lblBody = new QLabel(this);
|
||||||
|
f.setPointSize(bodyFont.first);
|
||||||
|
f.setWeight(bodyFont.second);
|
||||||
|
_lblBody->setFont(f);
|
||||||
|
_lblBody->setText(tr("• Browse and input operation filename"));
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout();
|
||||||
|
layout->addWidget(_lblTitleLabel);
|
||||||
|
layout->addWidget(_lblSubtitle);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,30,QSizePolicy::Minimum, QSizePolicy::Fixed));
|
||||||
|
layout->addWidget(_lblBody);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,40,QSizePolicy::Minimum, QSizePolicy::Fixed));
|
||||||
|
layout->addLayout(t1);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Minimum, QSizePolicy::Expanding));
|
||||||
|
setLayout(layout);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wizardpage.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QLineEdit;
|
||||||
|
class QLabel;
|
||||||
|
class EvidencePage : public WizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
bool validatePage() override;
|
||||||
|
void initializePage() override;
|
||||||
|
EvidencePage(QWidget *parent = nullptr);
|
||||||
|
private:
|
||||||
|
QLineEdit * evidenceLine = nullptr;
|
||||||
|
QLabel *errorLabel = nullptr;
|
||||||
|
};
|
|
@ -0,0 +1,70 @@
|
||||||
|
#include "finishedpage.h"
|
||||||
|
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <appconfig.h>
|
||||||
|
|
||||||
|
void FinishedPage::initializePage()
|
||||||
|
{
|
||||||
|
auto shortCut = QKeySequence(AppConfig::value(CONFIG::SHORTCUT_CAPTUREWINDOW)).toString(QKeySequence::NativeText);
|
||||||
|
m_lblBody->setText(tr("\n\nYou can now submit evidence Try it now,\n Use %1 to capture the window").arg(shortCut));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FinishedPage::validatePage()
|
||||||
|
{
|
||||||
|
AppConfig::setValue(CONFIG::SHOW_WELCOME_SCREEN, QStringLiteral("false"));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FinishedPage::FinishedPage(QWidget *parent)
|
||||||
|
: WizardPage{Page_Finished, parent}
|
||||||
|
, m_lblBody{new QLabel(this)}
|
||||||
|
{
|
||||||
|
auto f = font();
|
||||||
|
auto _lblTitleLabel = new QLabel(this);
|
||||||
|
f.setPointSize(titleFont.first);
|
||||||
|
f.setWeight(titleFont.second);
|
||||||
|
_lblTitleLabel->setFont(f);
|
||||||
|
_lblTitleLabel->setText(tr("Congratulations!"));
|
||||||
|
|
||||||
|
auto _lblSubtitle = new QLabel(this);
|
||||||
|
f.setPointSize(subTitleFont.first);
|
||||||
|
f.setWeight(subTitleFont.second);
|
||||||
|
_lblSubtitle->setFont(f);
|
||||||
|
_lblSubtitle->setWordWrap(true);
|
||||||
|
_lblSubtitle->setText(tr("You have successfully completed the configuration setup and can continue working within the ashirt application as needed."));
|
||||||
|
|
||||||
|
f.setPointSize(bodyFont.first);
|
||||||
|
f.setWeight(bodyFont.second);
|
||||||
|
f.setItalic(true);
|
||||||
|
m_lblBody->setFont(f);
|
||||||
|
|
||||||
|
auto _lblBody2 = new QLabel(this);
|
||||||
|
f.setPointSize(bodyFont.first);
|
||||||
|
f.setWeight(bodyFont.second);
|
||||||
|
f.setItalic(true);
|
||||||
|
_lblBody2->setFont(f);
|
||||||
|
_lblBody2->setText(tr("\n\nFor more information or support"));
|
||||||
|
|
||||||
|
QString buttonStyle = QStringLiteral("QPushButton:enabled{background-color: rgba(93, 172, 232, 255);font:;color:\"black\";}");
|
||||||
|
auto _faqButton = new QPushButton(this);
|
||||||
|
_faqButton->setText(tr("Click here"));
|
||||||
|
_faqButton->setStyleSheet(buttonStyle);
|
||||||
|
connect(_faqButton, &QPushButton::clicked, this, [this]{
|
||||||
|
QDesktopServices::openUrl(QUrl(QStringLiteral("https://ashirt.io"), QUrl::TolerantMode));
|
||||||
|
});
|
||||||
|
|
||||||
|
auto hLayout = new QHBoxLayout();
|
||||||
|
hLayout->addWidget(_lblBody2, 8, Qt::AlignLeft | Qt::AlignBottom);
|
||||||
|
hLayout->addWidget(_faqButton, 2, Qt::AlignLeft | Qt::AlignBottom);
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout();
|
||||||
|
layout->addWidget(_lblTitleLabel);
|
||||||
|
layout->addWidget(_lblSubtitle);
|
||||||
|
layout->addWidget(m_lblBody);
|
||||||
|
layout->addLayout(hLayout);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Minimum, QSizePolicy::Expanding));
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wizardpage.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QLabel;
|
||||||
|
class FinishedPage : public WizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
void initializePage() override;
|
||||||
|
bool validatePage() override;
|
||||||
|
FinishedPage(QWidget *parent = nullptr);
|
||||||
|
private:
|
||||||
|
QLabel * m_lblBody = nullptr;
|
||||||
|
};
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include "firstTimeWizard.h"
|
||||||
|
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QKeySequenceEdit>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLine>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <releaseinfo.h>
|
||||||
|
#include <appconfig.h>
|
||||||
|
#include <QFileDialog>
|
||||||
|
|
||||||
|
#include "requirementspage.h"
|
||||||
|
#include "evidencepage.h"
|
||||||
|
#include "apikeyspage.h"
|
||||||
|
#include "hostpathpage.h"
|
||||||
|
#include "hosttestpage.h"
|
||||||
|
#include "captureareapage.h"
|
||||||
|
|
||||||
|
#include "capturewindowpage.h"
|
||||||
|
#include "captureclipboardpage.h"
|
||||||
|
#include "opspage.h"
|
||||||
|
#include "finishedpage.h"
|
||||||
|
|
||||||
|
FirstTimeWizard::FirstTimeWizard()
|
||||||
|
{
|
||||||
|
setFixedSize(780, 480);
|
||||||
|
setWizardStyle(ModernStyle);
|
||||||
|
|
||||||
|
setOption(QWizard::NoCancelButton, true);
|
||||||
|
setOption(QWizard::NoDefaultButton, true);
|
||||||
|
setPage(WizardPage::Page_Requiments, new RequirementsPage(this));
|
||||||
|
setPage(WizardPage::Page_Evidence, new EvidencePage(this));
|
||||||
|
setPage(WizardPage::Page_HostPath, new HostPathPage(this));
|
||||||
|
setPage(WizardPage::Page_Api, new ApiKeysPage(this));
|
||||||
|
setPage(WizardPage::Page_HostTest, new HostTestPage(this));
|
||||||
|
setPage(WizardPage::Page_CaptureArea, new CaptureAreaPage(this));
|
||||||
|
setPage(WizardPage::Page_CaptureWindow, new CaptureWindowPage(this));
|
||||||
|
setPage(WizardPage::Page_CaptureClipboard, new CaptureClipboardPage(this));
|
||||||
|
setPage(WizardPage::Page_Ops, new OpsPage(this));
|
||||||
|
setPage(WizardPage::Page_Finished, new FinishedPage(this));
|
||||||
|
setStartId(WizardPage::Page_Requiments);
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
//Settings Wizard Chris Rizzitello 2023
|
||||||
|
#pragma once
|
||||||
|
#include <QWizard>
|
||||||
|
|
||||||
|
class FirstTimeWizard : public QWizard
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
FirstTimeWizard();
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
#include "hostpathpage.h"
|
||||||
|
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <appconfig.h>
|
||||||
|
|
||||||
|
bool HostPathPage::validatePage()
|
||||||
|
{
|
||||||
|
return field("host.url").isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HostPathPage::initializePage()
|
||||||
|
{
|
||||||
|
QString hostPath = AppConfig::value(CONFIG::APIURL);
|
||||||
|
setField("host.url", hostPath);
|
||||||
|
hostPathLine->setText(hostPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
HostPathPage::HostPathPage(QWidget *parent)
|
||||||
|
: WizardPage{Page_HostPath, parent}
|
||||||
|
{
|
||||||
|
auto f = font();
|
||||||
|
auto _lblTitleLabel = new QLabel(this);
|
||||||
|
f.setPointSize(titleFont.first);
|
||||||
|
f.setWeight(titleFont.second);
|
||||||
|
_lblTitleLabel->setFont(f);
|
||||||
|
_lblTitleLabel->setText(tr("Server URL"));
|
||||||
|
|
||||||
|
auto _lblSubtitle = new QLabel(this);
|
||||||
|
f.setPointSize(subTitleFont.first);
|
||||||
|
f.setWeight(subTitleFont.second);
|
||||||
|
_lblSubtitle->setFont(f);
|
||||||
|
_lblSubtitle->setWordWrap(true);
|
||||||
|
_lblSubtitle->setText(tr("The URL of the ashirt server. Example below:"));
|
||||||
|
|
||||||
|
auto _lblSubtitle2 = new QLabel(this);
|
||||||
|
f.setPointSize(subTitleFont.first);
|
||||||
|
f.setWeight(subTitleFont.second);
|
||||||
|
f.setItalic(true);
|
||||||
|
_lblSubtitle2->setFont(f);
|
||||||
|
_lblSubtitle2->setWordWrap(true);
|
||||||
|
_lblSubtitle2->setText(tr("http://localhost:8080"));
|
||||||
|
|
||||||
|
auto _lblBody = new QLabel(this);
|
||||||
|
f.setPointSize(bodyFont.first);
|
||||||
|
f.setWeight(bodyFont.second);
|
||||||
|
f.setItalic(false);
|
||||||
|
_lblBody->setFont(f);
|
||||||
|
_lblBody->setWordWrap(true);
|
||||||
|
_lblBody->setText(tr("• Enter the URL that was provided by admin"));
|
||||||
|
|
||||||
|
auto _lblPath = new QLabel(this);
|
||||||
|
f.setPointSize(smallFont.first);
|
||||||
|
f.setWeight(smallFont.second);
|
||||||
|
_lblPath->setFont(f);
|
||||||
|
_lblPath->setText(tr("Server URL:"));
|
||||||
|
|
||||||
|
hostPathLine = new QLineEdit(this);
|
||||||
|
hostPathLine->setTextMargins(3,0,3,0);
|
||||||
|
registerField("host.url*", hostPathLine);
|
||||||
|
|
||||||
|
auto t1 = new QVBoxLayout();
|
||||||
|
t1->setSpacing(1);
|
||||||
|
t1->addWidget(_lblPath);
|
||||||
|
t1->addWidget(hostPathLine);
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout();
|
||||||
|
layout->addWidget(_lblTitleLabel);
|
||||||
|
layout->addWidget(_lblSubtitle);
|
||||||
|
layout->addWidget(_lblSubtitle2);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,30,QSizePolicy::Minimum, QSizePolicy::Fixed));
|
||||||
|
layout->addWidget(_lblBody);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,60,QSizePolicy::Minimum, QSizePolicy::Fixed));
|
||||||
|
layout->addLayout(t1);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Minimum, QSizePolicy::Expanding));
|
||||||
|
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wizardpage.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QLineEdit;
|
||||||
|
class HostPathPage : public WizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
bool validatePage() override;
|
||||||
|
void initializePage() override;
|
||||||
|
HostPathPage(QWidget *parent = nullptr);
|
||||||
|
private:
|
||||||
|
QLineEdit * hostPathLine = nullptr;
|
||||||
|
};
|
|
@ -0,0 +1,156 @@
|
||||||
|
#include "hosttestpage.h"
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QMovie>
|
||||||
|
#include <QPaintEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QCheckBox>
|
||||||
|
|
||||||
|
#include "helpers/netman.h"
|
||||||
|
|
||||||
|
HostTestPage::HostTestPage(QWidget *parent)
|
||||||
|
: WizardPage{Page_HostTest, parent}
|
||||||
|
, timer{new QTimer(this)}
|
||||||
|
{
|
||||||
|
setCommitPage(true);
|
||||||
|
timer->setSingleShot(false);
|
||||||
|
|
||||||
|
connect(NetMan::get(), &NetMan::testStatusChanged, this, &HostTestPage::testResultsChanged);
|
||||||
|
|
||||||
|
connect(timer, &QTimer::timeout, this, [this] {
|
||||||
|
f = (f > 359) ? 0 : f+=1;
|
||||||
|
update();
|
||||||
|
});
|
||||||
|
auto f = font();
|
||||||
|
auto _lblTitleLabel = new QLabel(this);
|
||||||
|
f.setPointSize(titleFont.first);
|
||||||
|
f.setWeight(titleFont.second);
|
||||||
|
_lblTitleLabel->setFont(f);
|
||||||
|
_lblTitleLabel->setText(tr("Testing Server Connection"));
|
||||||
|
|
||||||
|
//Hidden Check box to allow us to have a manditory key for going foward
|
||||||
|
auto isReady = new QCheckBox(this);
|
||||||
|
isReady->setVisible(false);
|
||||||
|
registerField("host.accessable*", isReady);
|
||||||
|
|
||||||
|
auto layout = new QVBoxLayout();
|
||||||
|
layout->addWidget(_lblTitleLabel);
|
||||||
|
layout->addSpacerItem(new QSpacerItem(0,300,QSizePolicy::Minimum, QSizePolicy::Expanding));
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HostTestPage::validatePage()
|
||||||
|
{
|
||||||
|
if(!field("host.accessable").toBool())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
AppConfig::setValue(CONFIG::ACCESSKEY, field("host.accessKey").toString());
|
||||||
|
AppConfig::setValue(CONFIG::SECRETKEY, field("host.secretKey").toString());
|
||||||
|
AppConfig::setValue(CONFIG::APIURL, field("host.url").toString());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HostTestPage::initializePage()
|
||||||
|
{
|
||||||
|
f=0;
|
||||||
|
setField("host.accessable", false);
|
||||||
|
connect(wizard(), &QWizard::currentIdChanged, this, &HostTestPage::timerCheck, Qt::UniqueConnection);
|
||||||
|
NetMan::testConnection(field("host.url").toString(), field("host.accessKey").toString(), field("host.secretKey").toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void HostTestPage::paintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
WizardPage::paintEvent(event);
|
||||||
|
QPixmap tmp(250,250);
|
||||||
|
QPainter p(&tmp);
|
||||||
|
|
||||||
|
p.fillRect(tmp.rect(), palette().base());
|
||||||
|
p.setRenderHint(QPainter::Antialiasing, true);
|
||||||
|
p.setRenderHint(QPainter::TextAntialiasing, true);
|
||||||
|
p.setPen(QPen(palette().text().color(), 8));
|
||||||
|
p.drawEllipse(25, 25, 200, 200);
|
||||||
|
|
||||||
|
if ( currentState == NetMan::INPROGRESS) {
|
||||||
|
p.translate(125, 125);
|
||||||
|
p.rotate(f);
|
||||||
|
p.translate(-125, -125);
|
||||||
|
p.setBrush(QBrush( isDarkMode() ? QColor(0x6B,0x7F,0x8B) : QColor(0x5B,0x6C,0x76)));
|
||||||
|
p.drawEllipse(113, 13, 24,24);
|
||||||
|
}
|
||||||
|
p.end();
|
||||||
|
|
||||||
|
QRect drawArea (154,88,250,250);
|
||||||
|
QRect errorArea (0, 351, 555, 48);
|
||||||
|
|
||||||
|
static QFont errorFont = QFont("Helvetica Neue", 16, QFont::Normal);
|
||||||
|
errorFont.setStyleStrategy(QFont::StyleStrategy(QFont::PreferQuality | QFont::PreferAntialias));
|
||||||
|
|
||||||
|
static QFont statusFont = QFont("Helvetica Neue", 24, QFont::Normal);
|
||||||
|
statusFont.setStyleStrategy(QFont::StyleStrategy(QFont::PreferQuality | QFont::PreferAntialias));
|
||||||
|
|
||||||
|
static QFont checkFont = QFont("Helvetica Neue", 42, QFont::ExtraBold);
|
||||||
|
checkFont.setStyleStrategy(QFont::StyleStrategy(QFont::PreferQuality | QFont::NoSubpixelAntialias));
|
||||||
|
|
||||||
|
QPainter t (this);
|
||||||
|
t.setRenderHint(QPainter::TextAntialiasing, true);
|
||||||
|
t.setRenderHint(QPainter::Antialiasing, true);
|
||||||
|
|
||||||
|
t.drawPixmap(drawArea, tmp);
|
||||||
|
|
||||||
|
QTextOption textOptions;
|
||||||
|
textOptions.setAlignment(Qt::AlignCenter);
|
||||||
|
|
||||||
|
t.setFont(errorFont);
|
||||||
|
t.drawText(errorArea, NetMan::lastTestError(), textOptions);
|
||||||
|
|
||||||
|
t.translate(154, 88);
|
||||||
|
QRect iconArea (91, 50, 72, 72);
|
||||||
|
QRect labelArea (55,130,140,48);
|
||||||
|
QRect testLabelArea(55,100,140,48);
|
||||||
|
|
||||||
|
t.setPen(palette().text().color());
|
||||||
|
switch (currentState) {
|
||||||
|
case NetMan::INPROGRESS:
|
||||||
|
t.setFont(statusFont);
|
||||||
|
t.drawText(testLabelArea, "Testing", textOptions);
|
||||||
|
break;
|
||||||
|
case NetMan::SUCCESS:
|
||||||
|
t.setFont(checkFont);
|
||||||
|
t.drawText(iconArea, QStringLiteral("✓"), textOptions);
|
||||||
|
t.setFont(statusFont);
|
||||||
|
t.drawText(labelArea, "Success!", textOptions) ;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
t.setFont(checkFont);
|
||||||
|
t.drawText(iconArea, QStringLiteral("X"), textOptions);
|
||||||
|
t.setFont(statusFont);
|
||||||
|
t.drawText(labelArea, "Failed", textOptions);
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
t.end();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void HostTestPage::testResultsChanged(int result)
|
||||||
|
{
|
||||||
|
currentState = result;
|
||||||
|
timerCheck();
|
||||||
|
setField("host.accessable", (currentState == NetMan::SUCCESS));
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HostTestPage::timerCheck()
|
||||||
|
{
|
||||||
|
if(wizard()->currentId() == id()) {
|
||||||
|
f=0;
|
||||||
|
if (currentState == NetMan::INPROGRESS)
|
||||||
|
timer->start(33);
|
||||||
|
else
|
||||||
|
timer->stop();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
timer->stop();
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wizardpage.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QLabel;
|
||||||
|
class QNetworkReply;
|
||||||
|
class HostTestPage : public WizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
HostTestPage(QWidget *parent = nullptr);
|
||||||
|
protected:
|
||||||
|
bool validatePage() override;
|
||||||
|
void initializePage() override;
|
||||||
|
void paintEvent(QPaintEvent*) override;
|
||||||
|
private:
|
||||||
|
void testResultsChanged(int result);
|
||||||
|
void timerCheck();
|
||||||
|
int f=0;
|
||||||
|
QTimer *timer = nullptr;
|
||||||
|
QNetworkReply *currentTestReply = nullptr;
|
||||||
|
int currentState;
|
||||||
|
};
|
|
@ -0,0 +1,148 @@
|
||||||
|
#include "opspage.h"
|
||||||
|
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <appconfig.h>
|
||||||
|
|
||||||
|
#include "helpers/netman.h"
|
||||||
|
|
||||||
|
#include <dtos/ashirt_error.h>
|
||||||
|
|
||||||
|
bool OpsPage::validatePage()
|
||||||
|
{
|
||||||
|
if (!field("ops").isValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QString slug = opsCombo->currentData().toString();
|
||||||
|
QString name = opsCombo->currentText();
|
||||||
|
|
||||||
|
if(!_OpsList.contains(name)) {
|
||||||
|
slug = name.toLower().replace(invalidCharsRegex, QStringLiteral("-")).replace(startOrEndDash, QString());
|
||||||
|
createOpReply = NetMan::createOperation(name, slug);
|
||||||
|
connect(createOpReply, &QNetworkReply::finished, this, &OpsPage::createOpComplete);
|
||||||
|
return successful;
|
||||||
|
}
|
||||||
|
AppConfig::setOperationDetails(slug, name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpsPage::initializePage()
|
||||||
|
{
|
||||||
|
NetMan::refreshOperationsList();
|
||||||
|
int v = opsCombo->findText(AppConfig::operationName());
|
||||||
|
setField("ops", v);
|
||||||
|
opsCombo->setCurrentIndex(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
OpsPage::OpsPage(QWidget *parent)
|
||||||
|
: WizardPage{Page_Ops, parent}
|
||||||
|
{
|
||||||
|
connect(NetMan::get(), &NetMan::operationListUpdated, this, &OpsPage::operationsUpdated);
|
||||||
|
auto f = font();
|
||||||
|
|
||||||
|
auto _lblTitleLabel = new QLabel(this);
|
||||||
|
f.setPointSize(titleFont.first);
|
||||||
|
f.setWeight(titleFont.second);
|
||||||
|
_lblTitleLabel->setFont(f);
|
||||||
|
_lblTitleLabel->setText(tr("Select or Create Operation"));
|
||||||
|
|
||||||
|
auto _lblSubtitle = new QLabel(this);
|
||||||
|
f.setPointSize(subTitleFont.first);
|
||||||
|
f.setWeight(subTitleFont.second);
|
||||||
|
_lblSubtitle->setFont(f);
|
||||||
|
_lblSubtitle->setWordWrap(true);
|
||||||
|
_lblSubtitle->setText(tr("Select the desired operation below. If none exist you can create a new one."));
|
||||||
|
|
||||||
|
auto _lblBody = new QLabel(this);
|
||||||
|
f.setPointSize(bodyFont.first);
|
||||||
|
f.setWeight(bodyFont.second);
|
||||||
|
_lblBody->setFont(f);
|
||||||
|
_lblBody->setWordWrap(true);
|
||||||
|
_lblBody->setText(tr("• Select the desired operation below. If none exist you can create a new one."));
|
||||||
|
|
||||||
|
auto _lblBody2 = new QLabel(this);
|
||||||
|
f.setPointSize(bodyFont.first);
|
||||||
|
f.setWeight(bodyFont.second);
|
||||||
|
_lblBody2->setFont(f);
|
||||||
|
_lblBody2->setWordWrap(true);
|
||||||
|
_lblBody2->setText(tr("• The user that creates an operation automatically becomes the admin, and can assign access to additional users in the ashirt server."));
|
||||||
|
|
||||||
|
auto _lblEvidence = new QLabel(this);
|
||||||
|
f.setPointSize(smallFont.first);
|
||||||
|
f.setWeight(smallFont.second);
|
||||||
|
_lblEvidence->setFont(f);
|
||||||
|
_lblEvidence->setText(tr("Operation Name:"));
|
||||||
|
|
||||||
|
opsCombo = new QComboBox(this);
|
||||||
|
registerField("ops", opsCombo);
|
||||||
|
|
||||||
|
responseLabel = new QLabel(this);
|
||||||
|
f.setPointSize(smallFont.first);
|
||||||
|
f.setWeight(smallFont.second);
|
||||||
|
responseLabel->setFont(f);
|
||||||
|
|
||||||
|
auto t1 = new QVBoxLayout();
|
||||||
|
t1->setSpacing(1);
|
||||||
|
t1->addWidget(_lblEvidence);
|
||||||
|
t1->addWidget(opsCombo);
|
||||||
|
t1->addWidget(responseLabel);
|
||||||
|
|
||||||
|
auto topLayout = new QVBoxLayout();
|
||||||
|
topLayout->addWidget(_lblTitleLabel);
|
||||||
|
topLayout->addWidget(_lblSubtitle);
|
||||||
|
topLayout->addSpacerItem(new QSpacerItem(0,20,QSizePolicy::Minimum, QSizePolicy::Fixed));
|
||||||
|
topLayout->addWidget(_lblBody);
|
||||||
|
topLayout->addSpacerItem(new QSpacerItem(0,10,QSizePolicy::Minimum, QSizePolicy::Fixed));
|
||||||
|
topLayout->addWidget(_lblBody2);
|
||||||
|
topLayout->addSpacerItem(new QSpacerItem(0,50,QSizePolicy::Minimum, QSizePolicy::Fixed));
|
||||||
|
topLayout->addLayout(t1);
|
||||||
|
topLayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Minimum, QSizePolicy::Expanding));
|
||||||
|
setLayout(topLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpsPage::operationsUpdated(bool success, const QList<dto::Operation> & operations)
|
||||||
|
{
|
||||||
|
if (!success)
|
||||||
|
return;
|
||||||
|
|
||||||
|
opsCombo->clear();
|
||||||
|
opsCombo->setEditable(true);
|
||||||
|
_OpsList.clear();
|
||||||
|
for (const auto& op : operations) {
|
||||||
|
_OpsList.insert(op.name, op.slug);
|
||||||
|
opsCombo->addItem(op.name, op.slug);
|
||||||
|
}
|
||||||
|
int v = opsCombo->findText(AppConfig::operationName());
|
||||||
|
setField("ops", v);
|
||||||
|
opsCombo->setCurrentIndex(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpsPage::createOpComplete()
|
||||||
|
{
|
||||||
|
bool isValid;
|
||||||
|
auto data = NetMan::extractResponse(createOpReply, isValid);
|
||||||
|
if (isValid) {
|
||||||
|
dto::Operation op = dto::Operation::parseData(data);
|
||||||
|
AppConfig::setOperationDetails(op.slug, op.name);
|
||||||
|
NetMan::refreshOperationsList();
|
||||||
|
cleanUpReply(&createOpReply);
|
||||||
|
successful = true;
|
||||||
|
wizard()->next();
|
||||||
|
} else {
|
||||||
|
setField("ops", -1);
|
||||||
|
successful = false;
|
||||||
|
cleanUpReply(&createOpReply);
|
||||||
|
dto::AShirtError err = dto::AShirtError::parseData(data);
|
||||||
|
if (err.error.contains(QStringLiteral("slug already exists"))) {
|
||||||
|
responseLabel->setText(tr("A similar operation name already exists. Please try a new name."));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
responseLabel->setText(tr("Got an unexpected error: %1").arg(err.error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wizardpage.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "dtos/operation.h"
|
||||||
|
|
||||||
|
class QNetworkReply;
|
||||||
|
class QLabel;
|
||||||
|
class QComboBox;
|
||||||
|
class OpsPage : public WizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
bool validatePage() override;
|
||||||
|
void initializePage() override;
|
||||||
|
OpsPage(QWidget *parent = nullptr);
|
||||||
|
private:
|
||||||
|
void operationsUpdated(bool success, const QList<dto::Operation> & operations);
|
||||||
|
void createOpComplete();
|
||||||
|
QLabel *responseLabel = nullptr;
|
||||||
|
QComboBox *opsCombo = nullptr;
|
||||||
|
QNetworkReply* createOpReply = nullptr;
|
||||||
|
QMap<QString, QString> _OpsList;
|
||||||
|
inline static const QRegularExpression invalidCharsRegex = QRegularExpression(QStringLiteral("[^A-Za-z0-9]+"));
|
||||||
|
inline static const QRegularExpression startOrEndDash = QRegularExpression(QStringLiteral("^-|-$"));
|
||||||
|
bool successful= false;
|
||||||
|
};
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include "requirementspage.h"
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
RequirementsPage::RequirementsPage(QWidget *parent)
|
||||||
|
: WizardPage{Page_Requiments, parent}
|
||||||
|
{
|
||||||
|
auto f = font();
|
||||||
|
|
||||||
|
auto _lblTitleLabel = new QLabel(this);
|
||||||
|
f.setPointSize(titleFont.first);
|
||||||
|
f.setWeight(titleFont.second);
|
||||||
|
_lblTitleLabel->setFont(f);
|
||||||
|
_lblTitleLabel->setText(tr("Requirements"));
|
||||||
|
|
||||||
|
auto _lblSubtitle = new QLabel(this);
|
||||||
|
f.setPointSize(subTitleFont.first);
|
||||||
|
f.setWeight(subTitleFont.second);
|
||||||
|
_lblSubtitle->setFont(f);
|
||||||
|
_lblSubtitle->setWordWrap(true);
|
||||||
|
_lblSubtitle->setText(tr("To get started, make sure you have acquired the following information from your admin:"));
|
||||||
|
|
||||||
|
auto _lblBody = new QLabel(this);
|
||||||
|
f.setPointSize(bodyFont.first);
|
||||||
|
f.setWeight(bodyFont.second);
|
||||||
|
_lblBody->setFont(f);
|
||||||
|
_lblBody->setText(tr("\n\n\n\t• URL for the ashirt server\n\n\t• Login method"));
|
||||||
|
|
||||||
|
auto topLayout = new QVBoxLayout();
|
||||||
|
topLayout->addWidget(_lblTitleLabel);
|
||||||
|
topLayout->addWidget(_lblSubtitle);
|
||||||
|
topLayout->addWidget(_lblBody);
|
||||||
|
topLayout->addSpacerItem(new QSpacerItem(0,0,QSizePolicy::Minimum, QSizePolicy::Expanding));
|
||||||
|
setLayout(topLayout);
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "wizardpage.h"
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class RequirementsPage : public WizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
RequirementsPage(QWidget *parent = nullptr);
|
||||||
|
};
|
|
@ -0,0 +1,163 @@
|
||||||
|
#include "welcomepage.h"
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QGridLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLine>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <releaseinfo.h>
|
||||||
|
#include <appconfig.h>
|
||||||
|
|
||||||
|
WelcomePage::WelcomePage(QWidget *parent)
|
||||||
|
: AShirtDialog{parent}
|
||||||
|
, m_sideGrad{QLinearGradient(0,0, m_side_w, m_side_h)}
|
||||||
|
|
||||||
|
{
|
||||||
|
m_sideGrad.setColorAt(0, QColor(0x2E, 0x33, 0x37));
|
||||||
|
m_sideGrad.setColorAt(1, QColor(0x1D, 0x20, 0x24));
|
||||||
|
setFixedSize(780, 468);
|
||||||
|
QString buttonStyle = QStringLiteral("QPushButton:enabled{\
|
||||||
|
background-color: rgba(93, 172, 232, 255);\
|
||||||
|
font:;color:\"black\";}");
|
||||||
|
|
||||||
|
auto f = font();
|
||||||
|
|
||||||
|
auto _lblTitleLabel = new QLabel(this);
|
||||||
|
f.setPointSize(m_titleFontSize);
|
||||||
|
f.setBold(true);
|
||||||
|
_lblTitleLabel->setFont(f);
|
||||||
|
_lblTitleLabel->setText(tr("Welcome!"));
|
||||||
|
|
||||||
|
auto _lblSubtitle = new QLabel(this);
|
||||||
|
f.setPointSize(m_subTitleFontSize);
|
||||||
|
f.setBold(false);
|
||||||
|
_lblSubtitle->setFont(f);
|
||||||
|
_lblSubtitle->setText(tr("Click on the Ashirt tray icon to begin"));
|
||||||
|
|
||||||
|
auto topLayout = new QVBoxLayout();
|
||||||
|
topLayout->addWidget(_lblTitleLabel);
|
||||||
|
topLayout->addWidget(_lblSubtitle);
|
||||||
|
auto tGrid = new QGridLayout();
|
||||||
|
tGrid->setContentsMargins(215, 20, 20, 20);
|
||||||
|
tGrid->addLayout(topLayout, 0, 0, 6, 5);
|
||||||
|
tGrid->setVerticalSpacing(15);
|
||||||
|
|
||||||
|
auto startSetup = new QPushButton(this);
|
||||||
|
startSetup->setStyleSheet(buttonStyle);
|
||||||
|
startSetup->setText(tr("Start Setup"));
|
||||||
|
connect(startSetup, &QPushButton::clicked, this, [this]{
|
||||||
|
close();
|
||||||
|
Q_EMIT requestSetupWizard();
|
||||||
|
});
|
||||||
|
|
||||||
|
auto _lblTopLabel = new QLabel(this);
|
||||||
|
f.setPointSize(m_h3FontSize);
|
||||||
|
f.setBold(true);
|
||||||
|
_lblTopLabel->setFont(f);
|
||||||
|
_lblTopLabel->setText(tr("New Users"));
|
||||||
|
|
||||||
|
auto _lblTopBody = new QLabel(this);
|
||||||
|
f.setPointSize(m_bodyFontSize);
|
||||||
|
f.setBold(false);
|
||||||
|
_lblTopBody->setFont(f);
|
||||||
|
_lblTopBody->setText(tr("On your first launch, you must setup an appropriate\nconfiguration with our setup wizard."));
|
||||||
|
auto line = new QFrame(this);
|
||||||
|
line->setFrameStyle(QFrame::HLine);
|
||||||
|
|
||||||
|
tGrid->addWidget(_lblTopLabel, 7, 0, 2, 5, Qt::AlignLeft | Qt::AlignTop);
|
||||||
|
tGrid->addWidget(_lblTopBody, 8, 0, 4, 4, Qt::AlignLeft | Qt::AlignBottom);
|
||||||
|
tGrid->addWidget(startSetup, 8, 5, 6, 1, Qt::AlignVCenter);
|
||||||
|
tGrid->addWidget(line ,12 , 0, 1, 6, Qt::AlignVCenter);
|
||||||
|
|
||||||
|
auto _lblMidLabel = new QLabel(this);
|
||||||
|
f.setPointSize(m_h3FontSize);
|
||||||
|
f.setBold(true);
|
||||||
|
_lblMidLabel->setFont(f);
|
||||||
|
_lblMidLabel->setText(tr("Explore the Server"));
|
||||||
|
|
||||||
|
auto _lblMidBody = new QLabel(this);
|
||||||
|
f.setPointSize(m_bodyFontSize);
|
||||||
|
f.setBold(false);
|
||||||
|
_lblMidBody->setFont(f);
|
||||||
|
_lblMidBody->setText(tr("This is our frontend web toolkit that allows ease of use with\ntesting operations and viewing evience."));
|
||||||
|
auto viewServer = new QPushButton(this);
|
||||||
|
viewServer->setStyleSheet(buttonStyle);
|
||||||
|
connect(viewServer, &QPushButton::clicked, this, [this] {
|
||||||
|
QDesktopServices::openUrl(QUrl(QStringLiteral("https://github.com/ashirt-ops/ashirt-server"), QUrl::TolerantMode));
|
||||||
|
});
|
||||||
|
viewServer->setText(tr("Download"));
|
||||||
|
|
||||||
|
auto line2 = new QFrame(this);
|
||||||
|
line2->setFrameStyle(QFrame::HLine);
|
||||||
|
|
||||||
|
tGrid->addWidget(_lblMidLabel, 13, 0, 2, 5, Qt::AlignLeft | Qt::AlignTop);
|
||||||
|
tGrid->addWidget(_lblMidBody, 14, 0, 4, 4, Qt::AlignLeft | Qt::AlignBottom);
|
||||||
|
tGrid->addWidget(viewServer, 14, 5, 6, 1, Qt::AlignVCenter);
|
||||||
|
tGrid->addWidget(line2 ,18 , 0, 1, 6, Qt::AlignVCenter);
|
||||||
|
|
||||||
|
auto _lblBottomLabel = new QLabel(this);
|
||||||
|
f.setPointSize(m_h3FontSize);
|
||||||
|
f.setBold(true);
|
||||||
|
_lblBottomLabel->setFont(f);
|
||||||
|
_lblBottomLabel->setText(tr("Quick Docs"));
|
||||||
|
|
||||||
|
auto _lblBottomBody = new QLabel(this);
|
||||||
|
f.setPointSize(m_bodyFontSize);
|
||||||
|
f.setBold(false);
|
||||||
|
_lblBottomBody->setFont(f);
|
||||||
|
_lblBottomBody->setText(tr("For more information about ashirt, support and access to\ndocumentation or common user questions."));
|
||||||
|
auto learnMore = new QPushButton(this);
|
||||||
|
learnMore->setStyleSheet(buttonStyle);
|
||||||
|
connect(learnMore, &QPushButton::clicked, this, [this] {
|
||||||
|
QDesktopServices::openUrl(QUrl(QStringLiteral("https://ashirt.io"), QUrl::TolerantMode));
|
||||||
|
});
|
||||||
|
learnMore->setText(tr("Learn More"));
|
||||||
|
|
||||||
|
tGrid->addWidget(_lblBottomLabel, 19, 0, 2, 5, Qt::AlignLeft | Qt::AlignTop);
|
||||||
|
tGrid->addWidget(_lblBottomBody, 20, 0, 4, 4, Qt::AlignLeft | Qt::AlignBottom);
|
||||||
|
tGrid->addWidget(learnMore, 20, 5, 6, 1, Qt::AlignVCenter);
|
||||||
|
|
||||||
|
auto hide = new QCheckBox("Do Not show when starting", this);
|
||||||
|
hide->setChecked(AppConfig::value(CONFIG::SHOW_WELCOME_SCREEN) != "true");
|
||||||
|
connect(hide,&QCheckBox::stateChanged, this, [hide, this] (int newState) {
|
||||||
|
if(newState != Qt::Checked)
|
||||||
|
AppConfig::setValue(CONFIG::SHOW_WELCOME_SCREEN, "true");
|
||||||
|
else
|
||||||
|
AppConfig::setValue(CONFIG::SHOW_WELCOME_SCREEN, "false");
|
||||||
|
});
|
||||||
|
tGrid->addWidget(hide, 25, 0, 2, 6);
|
||||||
|
|
||||||
|
setLayout(tGrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WelcomePage::paintEvent(QPaintEvent *)
|
||||||
|
{
|
||||||
|
static QFont titleFont = QFont("Helvetica Neue", m_sideLargeFont, QFont::ExtraBold, false);
|
||||||
|
titleFont.setStyleHint(QFont::Helvetica, QFont::StyleStrategy(QFont::PreferQuality | QFont::PreferAntialias));
|
||||||
|
|
||||||
|
static QFont subFont = QFont("Helvetica Neue", m_sideSmallFont, QFont::Light, true);
|
||||||
|
subFont.setStyleHint(QFont::Helvetica, QFont::StyleStrategy(QFont::PreferQuality | QFont::PreferAntialias));
|
||||||
|
|
||||||
|
static QFont versionFont = QFont("Helvetica Neue", m_sideSmallFont, QFont::ExtraLight, false);
|
||||||
|
versionFont.setStyleHint(QFont::Helvetica, QFont::StyleStrategy(QFont::PreferQuality | QFont::PreferAntialias));
|
||||||
|
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
subFont.setWeight(QFont::Normal);
|
||||||
|
versionFont.setWeight(QFont::Light);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QPainter painter(this);
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||||
|
painter.setRenderHint(QPainter::TextAntialiasing, true);
|
||||||
|
painter.fillRect(0,0, 200, height(), m_sideGrad);
|
||||||
|
painter.drawPixmap(QRect(50, 135, 100, 100), QStringLiteral(":/icons/shirt-light.svg"));
|
||||||
|
painter.setPen(QColor(0xF5,0xFB,0xFF));
|
||||||
|
painter.setFont(titleFont);
|
||||||
|
painter.drawText(QRect(0, 227, 200, 251), QStringLiteral("ASHIRT"), QTextOption(Qt::AlignHCenter));
|
||||||
|
painter.setFont(subFont);
|
||||||
|
painter.drawText(QRect(25, 275, 175, 350), QStringLiteral("Adversary Simulators High-Fedelity Intelligence and Reporting Toolkit"));
|
||||||
|
painter.setFont(versionFont);
|
||||||
|
painter.drawText(QRect(0, 445, 200, 455), QStringLiteral("Version %1").arg(ReleaseInfo::version), QTextOption(Qt::AlignHCenter));
|
||||||
|
painter.end();
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
#pragma once
|
||||||
|
#include <QWidget>
|
||||||
|
#include "ashirtdialog/ashirtdialog.h"
|
||||||
|
|
||||||
|
class WelcomePage : public AShirtDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit WelcomePage(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void requestSetupWizard();
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent *);
|
||||||
|
private:
|
||||||
|
const int m_side_w = 200;
|
||||||
|
const int m_side_h = 468;
|
||||||
|
QLinearGradient m_sideGrad;
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
const int m_titleFontSize = 28;
|
||||||
|
const int m_subTitleFontSize = 20;
|
||||||
|
const int m_h3FontSize = 18;
|
||||||
|
const int m_bodyFontSize = 14;
|
||||||
|
const int m_sideLargeFont = 28;
|
||||||
|
const int m_sideSmallFont = 12;
|
||||||
|
|
||||||
|
#else
|
||||||
|
const int m_titleFontSize = 22;
|
||||||
|
const int m_subTitleFontSize = 16;
|
||||||
|
const int m_h3FontSize = 14;
|
||||||
|
const int m_bodyFontSize = 10;
|
||||||
|
const int m_sideLargeFont = 26;
|
||||||
|
const int m_sideSmallFont = 10;
|
||||||
|
#endif
|
||||||
|
};
|
|
@ -0,0 +1,253 @@
|
||||||
|
#include "wizardpage.h"
|
||||||
|
#include <QPen>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QEvent>
|
||||||
|
#include "system_helpers.h"
|
||||||
|
|
||||||
|
WizardPage::WizardPage(int pageId, QWidget *parent)
|
||||||
|
: QWizardPage{parent}
|
||||||
|
, m_id(pageId)
|
||||||
|
, m_sideGrad{QLinearGradient(0,0, m_side_w, m_side_h)}
|
||||||
|
{
|
||||||
|
m_sideGrad.setColorAt(0, QColor(0x2E, 0x33, 0x37));
|
||||||
|
m_sideGrad.setColorAt(1, QColor(0x1D, 0x20, 0x24));
|
||||||
|
|
||||||
|
setPixmap(QWizard::WatermarkPixmap, paintSideImage(m_id));
|
||||||
|
setStyleSheet(isDarkMode() ? _darkStyle : _lightStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WizardPage::changeEvent(QEvent *event)
|
||||||
|
{
|
||||||
|
if (event->type() == QEvent::PaletteChange) {
|
||||||
|
setStyleSheet(isDarkMode() ? _darkStyle : _lightStyle);
|
||||||
|
setPixmap(QWizard::WatermarkPixmap, paintSideImage(m_id));
|
||||||
|
event->accept();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event->ignore();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WizardPage::isDarkMode()
|
||||||
|
{
|
||||||
|
return !SystemHelpers::isLightTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap WizardPage::paintSideImage(int pageId)
|
||||||
|
{
|
||||||
|
QPen inactiveBubbleOutline = QPen(QColor(0x2D, 0x31, 0x35), 1);
|
||||||
|
QColor highlightedStep = QColor(0x79, 0xC5, 0xFF);
|
||||||
|
QString checkMark = QStringLiteral("✓");
|
||||||
|
|
||||||
|
QPixmap sideImage(m_side_w + 20, m_side_h);
|
||||||
|
QPainter painter;
|
||||||
|
|
||||||
|
painter.begin(&sideImage);
|
||||||
|
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing, true);
|
||||||
|
painter.setRenderHint(QPainter::TextAntialiasing, true);
|
||||||
|
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
|
||||||
|
|
||||||
|
QString fontFamily = "Helvetica Neue";
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
int sideFontSize = 14;
|
||||||
|
#elif defined Q_OS_WIN
|
||||||
|
int sideFontSize = 16;
|
||||||
|
#elif defined Q_OS_MAC
|
||||||
|
int sideFontSize = 22;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static QFont currentItemFont = QFont(fontFamily, sideFontSize, QFont::ExtraBold);
|
||||||
|
currentItemFont.setStyleHint(QFont::Helvetica, QFont::StyleStrategy(QFont::PreferQuality | QFont::PreferAntialias));
|
||||||
|
|
||||||
|
static QFont nonCurrentItemFont = QFont(fontFamily, sideFontSize, QFont::Light);
|
||||||
|
nonCurrentItemFont.setStyleHint(QFont::Helvetica, QFont::StyleStrategy(QFont::PreferQuality | QFont::PreferAntialias));
|
||||||
|
|
||||||
|
static QFont bubbleTextFont = QFont(fontFamily, sideFontSize, QFont::Normal);
|
||||||
|
bubbleTextFont.setStyleHint(QFont::Helvetica, QFont::StyleStrategy(QFont::PreferQuality | QFont::PreferAntialias));
|
||||||
|
|
||||||
|
static QFont bubbleCheckFont = QFont(fontFamily, sideFontSize, QFont::Normal);
|
||||||
|
bubbleCheckFont.setStyleHint(QFont::Helvetica, QFont::StyleStrategy(QFont::PreferQuality | QFont::NoSubpixelAntialias));
|
||||||
|
|
||||||
|
static QFont stepsFont = QFont(fontFamily, smallFont.first, smallFont.second);
|
||||||
|
stepsFont.setStyleHint(QFont::Helvetica, QFont::StyleStrategy(QFont::PreferQuality | QFont::PreferAntialias));
|
||||||
|
|
||||||
|
QColor inactiveBubbleColor = QColor(0x2D, 0x32, 0x36);
|
||||||
|
QString _textTemp;
|
||||||
|
//Background
|
||||||
|
painter.fillRect(0,0, sideImage.width() - 20, sideImage.height(), m_sideGrad);
|
||||||
|
painter.fillRect(m_side_w, 0 , 20, m_side_h, QBrush(palette().base().color()));
|
||||||
|
|
||||||
|
if(pageId == Page_Requiments) {
|
||||||
|
painter.setFont(currentItemFont);
|
||||||
|
painter.setPen(highlightedStep);
|
||||||
|
painter.setBrush(highlightedStep);
|
||||||
|
} else {
|
||||||
|
painter.setFont(nonCurrentItemFont);
|
||||||
|
painter.setPen(QPen(Qt::white));
|
||||||
|
painter.setBrush(inactiveBubbleColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.drawText(QRect(6, 30, 165, 32), Qt::AlignRight | Qt::AlignVCenter, QStringLiteral("Requirements"));
|
||||||
|
|
||||||
|
painter.setPen(inactiveBubbleOutline);
|
||||||
|
painter.drawEllipse(184, 30,32,32);
|
||||||
|
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
if(pageId == Page_Requiments) {
|
||||||
|
painter.setFont(bubbleTextFont);
|
||||||
|
_textTemp = QStringLiteral("1");
|
||||||
|
} else {
|
||||||
|
painter.setFont(bubbleCheckFont);
|
||||||
|
_textTemp = checkMark;
|
||||||
|
}
|
||||||
|
painter.drawText(QRect(184, 30,32,32), Qt::AlignCenter, _textTemp);
|
||||||
|
|
||||||
|
if(pageId == Page_Evidence) {
|
||||||
|
painter.setFont(currentItemFont);
|
||||||
|
painter.setPen(highlightedStep);
|
||||||
|
painter.setBrush(highlightedStep);
|
||||||
|
} else {
|
||||||
|
painter.setFont(nonCurrentItemFont);
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
painter.setBrush(inactiveBubbleColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.drawText(QRect(6,117,165,32), Qt::AlignRight | Qt::AlignVCenter, QStringLiteral("Evidence Path"));
|
||||||
|
painter.setPen(inactiveBubbleOutline);
|
||||||
|
painter.drawEllipse(184,117,32,32);
|
||||||
|
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
if(pageId < Page_HostPath) {
|
||||||
|
painter.setFont(bubbleTextFont);
|
||||||
|
_textTemp = QStringLiteral("2");
|
||||||
|
} else {
|
||||||
|
painter.setFont(bubbleCheckFont);
|
||||||
|
_textTemp = checkMark;
|
||||||
|
}
|
||||||
|
painter.drawText(QRect(184, 117, 32,32), Qt::AlignCenter, _textTemp);
|
||||||
|
|
||||||
|
if(pageId >= Page_HostPath && pageId < Page_CaptureArea) {
|
||||||
|
painter.setFont(currentItemFont);
|
||||||
|
painter.setPen(highlightedStep);
|
||||||
|
painter.setBrush(highlightedStep);
|
||||||
|
} else {
|
||||||
|
painter.setFont(nonCurrentItemFont);
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
painter.setBrush(inactiveBubbleColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.drawText(QRect(6, 204, 165, 32), Qt::AlignRight | Qt::AlignVCenter, QStringLiteral("Server Settings"));
|
||||||
|
painter.setPen(inactiveBubbleOutline);
|
||||||
|
|
||||||
|
if(pageId == Page_HostPath) {
|
||||||
|
painter.setBrush(highlightedStep);
|
||||||
|
painter.drawPie(184,204,32,32, 90*16, -120*16);
|
||||||
|
painter.setBrush(inactiveBubbleColor);
|
||||||
|
painter.drawPie(184,204, 32,32, 90*16, 240*16);
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
painter.setFont(stepsFont);
|
||||||
|
painter.drawText(QRect(0,229,200,16), Qt::AlignHCenter | Qt::AlignVCenter, QStringLiteral("Step 1 of 3"));
|
||||||
|
} else if(pageId == Page_Api) {
|
||||||
|
painter.setBrush(highlightedStep);
|
||||||
|
painter.drawPie(184,204,32,32, 90*16, -240*16);
|
||||||
|
painter.setBrush(inactiveBubbleColor);
|
||||||
|
painter.drawPie(184,204,32,32, 90*16, 120*16);
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
painter.setFont(stepsFont);
|
||||||
|
painter.drawText(QRect(0,229,200,16), Qt::AlignHCenter | Qt::AlignVCenter, QStringLiteral("Step 2 of 3"));
|
||||||
|
} else if(pageId == Page_HostTest) {
|
||||||
|
painter.drawEllipse(184,204,32,32);
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
painter.setFont(stepsFont);
|
||||||
|
painter.drawText(QRect(0,229,200,16), Qt::AlignHCenter | Qt::AlignVCenter, QStringLiteral("Step 3 of 3"));
|
||||||
|
} else {
|
||||||
|
painter.drawEllipse(184,204,32,32);
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
if(pageId < Page_CaptureArea) {
|
||||||
|
painter.setFont(bubbleTextFont);
|
||||||
|
_textTemp = QStringLiteral("3");
|
||||||
|
} else {
|
||||||
|
painter.setFont(bubbleCheckFont);
|
||||||
|
_textTemp = checkMark;
|
||||||
|
}
|
||||||
|
painter.drawText(QRect(184,204,32,32), Qt::AlignCenter, _textTemp);
|
||||||
|
|
||||||
|
if(pageId >= Page_CaptureArea && pageId < Page_Ops) {
|
||||||
|
painter.setFont(currentItemFont);
|
||||||
|
painter.setPen(highlightedStep);
|
||||||
|
painter.setBrush(highlightedStep);
|
||||||
|
} else {
|
||||||
|
painter.setFont(nonCurrentItemFont);
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
painter.setBrush(inactiveBubbleColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.drawText(QRect(6, 291, 165, 32), Qt::AlignRight | Qt::AlignVCenter, QStringLiteral("Input Settings"));
|
||||||
|
painter.setPen(inactiveBubbleOutline);
|
||||||
|
painter.drawEllipse(184,291,32,32);
|
||||||
|
|
||||||
|
if(pageId == Page_CaptureArea) {
|
||||||
|
painter.setBrush(highlightedStep);
|
||||||
|
painter.drawPie(184,291,32,32, 90*16, -120*16);
|
||||||
|
painter.setBrush(inactiveBubbleColor);
|
||||||
|
painter.drawPie(184,291, 32,32, 90*16, 240*16);
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
painter.setFont(stepsFont);
|
||||||
|
painter.drawText(QRect(0,316,200,16), Qt::AlignHCenter | Qt::AlignVCenter, QStringLiteral("Step 1 of 3"));
|
||||||
|
} else if(pageId == Page_CaptureWindow) {
|
||||||
|
painter.setBrush(highlightedStep);
|
||||||
|
painter.drawPie(184,291,32,32, 90*16, -240*16);
|
||||||
|
painter.setBrush(inactiveBubbleColor);
|
||||||
|
painter.drawPie(184,291,32,32, 90*16, 120*16);
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
painter.setFont(stepsFont);
|
||||||
|
painter.drawText(QRect(0,316,200,16), Qt::AlignHCenter | Qt::AlignVCenter, QStringLiteral("Step 2 of 3"));
|
||||||
|
} else if(pageId == Page_CaptureClipboard) {
|
||||||
|
painter.drawEllipse(184,291,32,32);
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
painter.setFont(stepsFont);
|
||||||
|
painter.drawText(QRect(0,316,200,16), Qt::AlignHCenter | Qt::AlignVCenter, QStringLiteral("Step 3 of 3"));
|
||||||
|
} else {
|
||||||
|
painter.drawEllipse(184,291,32,32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
if(pageId < Page_Ops) {
|
||||||
|
painter.setFont(bubbleTextFont);
|
||||||
|
_textTemp = QStringLiteral("4");
|
||||||
|
} else {
|
||||||
|
painter.setFont(bubbleCheckFont);
|
||||||
|
_textTemp = checkMark;
|
||||||
|
}
|
||||||
|
painter.drawText(QRect(184,291,32,32), Qt::AlignCenter, _textTemp);
|
||||||
|
|
||||||
|
if(pageId >= Page_Ops && pageId < Page_Finished) {
|
||||||
|
painter.setFont(currentItemFont);
|
||||||
|
painter.setPen(highlightedStep);
|
||||||
|
painter.setBrush(highlightedStep);
|
||||||
|
} else {
|
||||||
|
painter.setFont(nonCurrentItemFont);
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
painter.setBrush(inactiveBubbleColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.drawText(QRect(6, 378, 165, 32),Qt::AlignRight | Qt::AlignVCenter, QStringLiteral("Operation Name"));
|
||||||
|
painter.setPen(inactiveBubbleOutline);
|
||||||
|
painter.drawEllipse(184,378,32,32);
|
||||||
|
|
||||||
|
painter.setPen(Qt::white);
|
||||||
|
if(pageId != Page_Finished) {
|
||||||
|
painter.setFont(bubbleTextFont);
|
||||||
|
_textTemp = QStringLiteral("5");
|
||||||
|
} else {
|
||||||
|
painter.setFont(bubbleCheckFont);
|
||||||
|
_textTemp = checkMark;
|
||||||
|
}
|
||||||
|
painter.drawText(QRect(184,378,32,32),Qt::AlignCenter, _textTemp);
|
||||||
|
painter.end();
|
||||||
|
|
||||||
|
return sideImage;
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWizardPage>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class WizardPage : public QWizardPage
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
enum PAGE {
|
||||||
|
Page_Requiments = 0,
|
||||||
|
Page_Evidence,
|
||||||
|
Page_HostPath,
|
||||||
|
Page_Api,
|
||||||
|
Page_HostTest,
|
||||||
|
Page_CaptureArea,
|
||||||
|
Page_CaptureWindow,
|
||||||
|
Page_CaptureClipboard,
|
||||||
|
Page_Ops,
|
||||||
|
Page_Finished
|
||||||
|
};
|
||||||
|
WizardPage(int pageId = Page_Requiments, QWidget *parent = nullptr);
|
||||||
|
int id() {return m_id;}
|
||||||
|
protected:
|
||||||
|
void changeEvent(QEvent *event);
|
||||||
|
bool isDarkMode();
|
||||||
|
#ifdef Q_OS_MAC
|
||||||
|
const QPair<int, QFont::Weight> titleFont = QPair<int, QFont::Weight>(28, QFont::Bold);
|
||||||
|
const QPair<int, QFont::Weight> subTitleFont = QPair<int, QFont::Weight>(20, QFont::Normal);
|
||||||
|
const QPair<int, QFont::Weight> bodyFont = QPair<int, QFont::Weight>(18, QFont::Normal);
|
||||||
|
const QPair<int, QFont::Weight> smallFont = QPair<int, QFont::Weight>(12, QFont::Light);
|
||||||
|
#else
|
||||||
|
const QPair<int, QFont::Weight> titleFont = QPair<int, QFont::Weight>(22, QFont::Bold);
|
||||||
|
const QPair<int, QFont::Weight> subTitleFont = QPair<int, QFont::Weight>(14, QFont::Normal);
|
||||||
|
const QPair<int, QFont::Weight> bodyFont = QPair<int, QFont::Weight>(12, QFont::Normal);
|
||||||
|
const QPair<int, QFont::Weight> smallFont = QPair<int, QFont::Weight>(9, QFont::Normal);
|
||||||
|
#endif
|
||||||
|
private:
|
||||||
|
const int m_side_w = 200;
|
||||||
|
const int m_side_h = 468;
|
||||||
|
const int m_id;
|
||||||
|
QLinearGradient m_sideGrad;
|
||||||
|
QString _styleTemplate = QStringLiteral("QComboBox:editable,QLineEdit{background:rgba(%1,%2,%3,255);}");
|
||||||
|
QString _lightStyle = _styleTemplate.arg(QStringLiteral("235"), QStringLiteral("235"), QStringLiteral("235"));
|
||||||
|
QString _darkStyle = _styleTemplate.arg(QStringLiteral("21"), QStringLiteral("23"), QStringLiteral("26"));
|
||||||
|
|
||||||
|
QPixmap paintSideImage(int pageId);
|
||||||
|
};
|
|
@ -36,6 +36,7 @@ Settings::Settings(QWidget *parent)
|
||||||
, captureClipboardShortcutTextBox(new SingleStrokeKeySequenceEdit(this))
|
, captureClipboardShortcutTextBox(new SingleStrokeKeySequenceEdit(this))
|
||||||
, testConnectionButton(new LoadingButton(tr("Test Connection"), this))
|
, testConnectionButton(new LoadingButton(tr("Test Connection"), this))
|
||||||
, couldNotSaveSettingsMsg(new QErrorMessage(this))
|
, couldNotSaveSettingsMsg(new QErrorMessage(this))
|
||||||
|
, showWelcomeScreen(new QCheckBox(tr("Show Welcome Screen"), this))
|
||||||
{
|
{
|
||||||
buildUi();
|
buildUi();
|
||||||
wireUi();
|
wireUi();
|
||||||
|
@ -65,11 +66,13 @@ void Settings::buildUi() {
|
||||||
+---------------+-------------+------------+-------------+
|
+---------------+-------------+------------+-------------+
|
||||||
6 | CodeblkSh Lbl | [CodeblkSh TB] |
|
6 | CodeblkSh Lbl | [CodeblkSh TB] |
|
||||||
+---------------+-------------+------------+-------------+
|
+---------------+-------------+------------+-------------+
|
||||||
7 | Test Conn Btn | StatusLabel |
|
7 | [] Show Welcome Screen |
|
||||||
+---------------+-------------+------------+-------------+
|
+---------------+-------------+------------+-------------+
|
||||||
8 | Vertical spacer |
|
8 | Test Conn Btn | StatusLabel |
|
||||||
+---------------+-------------+------------+-------------+
|
+---------------+-------------+------------+-------------+
|
||||||
9 | Dialog button Box{save, cancel} |
|
9 | Vertical spacer |
|
||||||
|
+---------------+-------------+------------+-------------+
|
||||||
|
10 | Dialog button Box{save, cancel} |
|
||||||
+---------------+-------------+------------+-------------+
|
+---------------+-------------+------------+-------------+
|
||||||
*/
|
*/
|
||||||
auto gridLayout = new QGridLayout(this);
|
auto gridLayout = new QGridLayout(this);
|
||||||
|
@ -107,14 +110,17 @@ void Settings::buildUi() {
|
||||||
gridLayout->addWidget(captureClipboardShortcutTextBox, 6, 1);
|
gridLayout->addWidget(captureClipboardShortcutTextBox, 6, 1);
|
||||||
|
|
||||||
// row 7
|
// row 7
|
||||||
gridLayout->addWidget(testConnectionButton, 7, 0);
|
gridLayout->addWidget(showWelcomeScreen, 7, 1, 1, 5);
|
||||||
gridLayout->addWidget(connStatusLabel, 7, 1, 1, 4);
|
|
||||||
|
|
||||||
// row 8
|
// row 8
|
||||||
gridLayout->addItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding), 8, 0, 1, gridLayout->columnCount());
|
gridLayout->addWidget(testConnectionButton, 8, 0);
|
||||||
|
gridLayout->addWidget(connStatusLabel, 8, 1, 1, 4);
|
||||||
|
|
||||||
// row 9
|
// row 9
|
||||||
gridLayout->addWidget(buttonBox, 9, 0, 1, gridLayout->columnCount());
|
gridLayout->addItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Expanding), 9, 0, 1, gridLayout->columnCount());
|
||||||
|
|
||||||
|
// row 10
|
||||||
|
gridLayout->addWidget(buttonBox, 10, 0, 1, gridLayout->columnCount());
|
||||||
|
|
||||||
setLayout(gridLayout);
|
setLayout(gridLayout);
|
||||||
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
|
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
|
||||||
|
@ -175,6 +181,7 @@ void Settings::showEvent(QShowEvent *evt) {
|
||||||
captureWindowCmdTextBox->setText(AppConfig::value(CONFIG::COMMAND_CAPTUREWINDOW));
|
captureWindowCmdTextBox->setText(AppConfig::value(CONFIG::COMMAND_CAPTUREWINDOW));
|
||||||
captureWindowShortcutTextBox->setKeySequence(QKeySequence::fromString(AppConfig::value(CONFIG::SHORTCUT_CAPTUREWINDOW)));
|
captureWindowShortcutTextBox->setKeySequence(QKeySequence::fromString(AppConfig::value(CONFIG::SHORTCUT_CAPTUREWINDOW)));
|
||||||
captureClipboardShortcutTextBox->setKeySequence(QKeySequence::fromString(AppConfig::value(CONFIG::SHORTCUT_CAPTURECLIPBOARD)));
|
captureClipboardShortcutTextBox->setKeySequence(QKeySequence::fromString(AppConfig::value(CONFIG::SHORTCUT_CAPTURECLIPBOARD)));
|
||||||
|
showWelcomeScreen->setChecked(AppConfig::value(CONFIG::SHOW_WELCOME_SCREEN) == "true");
|
||||||
|
|
||||||
// re-enable form
|
// re-enable form
|
||||||
connStatusLabel->clear();
|
connStatusLabel->clear();
|
||||||
|
@ -209,6 +216,8 @@ void Settings::onSaveClicked() {
|
||||||
AppConfig::setValue(CONFIG::COMMAND_CAPTUREWINDOW, captureWindowCmdTextBox->text());
|
AppConfig::setValue(CONFIG::COMMAND_CAPTUREWINDOW, captureWindowCmdTextBox->text());
|
||||||
AppConfig::setValue(CONFIG::SHORTCUT_CAPTUREWINDOW, captureWindowShortcutTextBox->keySequence().toString());
|
AppConfig::setValue(CONFIG::SHORTCUT_CAPTUREWINDOW, captureWindowShortcutTextBox->keySequence().toString());
|
||||||
AppConfig::setValue(CONFIG::SHORTCUT_CAPTURECLIPBOARD, captureClipboardShortcutTextBox->keySequence().toString());
|
AppConfig::setValue(CONFIG::SHORTCUT_CAPTURECLIPBOARD, captureClipboardShortcutTextBox->keySequence().toString());
|
||||||
|
QString showWelcome = showWelcomeScreen->isChecked() ? "true" : "false";
|
||||||
|
AppConfig::setValue(CONFIG::SHOW_WELCOME_SCREEN, showWelcome);
|
||||||
|
|
||||||
HotkeyManager::updateHotkeys();
|
HotkeyManager::updateHotkeys();
|
||||||
close();
|
close();
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "ashirtdialog/ashirtdialog.h"
|
#include "ashirtdialog/ashirtdialog.h"
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
|
|
||||||
class HotkeyManager;
|
class HotkeyManager;
|
||||||
|
@ -75,4 +76,5 @@ class Settings : public AShirtDialog {
|
||||||
LoadingButton* testConnectionButton = nullptr;
|
LoadingButton* testConnectionButton = nullptr;
|
||||||
QPushButton* eviRepoBrowseButton = nullptr;
|
QPushButton* eviRepoBrowseButton = nullptr;
|
||||||
QErrorMessage* couldNotSaveSettingsMsg = nullptr;
|
QErrorMessage* couldNotSaveSettingsMsg = nullptr;
|
||||||
|
QCheckBox *showWelcomeScreen = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include "helpers/system_helpers.h"
|
#include "helpers/system_helpers.h"
|
||||||
#include "hotkeymanager.h"
|
#include "hotkeymanager.h"
|
||||||
#include "models/codeblock.h"
|
#include "models/codeblock.h"
|
||||||
|
#include "firstRunWizard/firstTimeWizard.h"
|
||||||
|
#include "firstRunWizard/welcomepage.h"
|
||||||
|
|
||||||
TrayManager::TrayManager(QWidget * parent, DatabaseConnection* db)
|
TrayManager::TrayManager(QWidget * parent, DatabaseConnection* db)
|
||||||
: QDialog(parent)
|
: QDialog(parent)
|
||||||
|
@ -51,6 +53,9 @@ TrayManager::TrayManager(QWidget * parent, DatabaseConnection* db)
|
||||||
// delayed so that windows can listen for get all ops signal
|
// delayed so that windows can listen for get all ops signal
|
||||||
NetMan::refreshOperationsList();
|
NetMan::refreshOperationsList();
|
||||||
QTimer::singleShot(5000, this, &TrayManager::checkForUpdate);
|
QTimer::singleShot(5000, this, &TrayManager::checkForUpdate);
|
||||||
|
|
||||||
|
if(AppConfig::value(CONFIG::SHOW_WELCOME_SCREEN) != "false")
|
||||||
|
showWelcomeScreen();
|
||||||
}
|
}
|
||||||
|
|
||||||
TrayManager::~TrayManager() {
|
TrayManager::~TrayManager() {
|
||||||
|
@ -156,6 +161,19 @@ void TrayManager::changeEvent(QEvent *event)
|
||||||
event->ignore();
|
event->ignore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TrayManager::showWizard()
|
||||||
|
{
|
||||||
|
auto gandalf = new FirstTimeWizard();
|
||||||
|
gandalf->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrayManager::showWelcomeScreen()
|
||||||
|
{
|
||||||
|
auto welcomePage = new WelcomePage(this);
|
||||||
|
connect(welcomePage, &WelcomePage::requestSetupWizard, this, &TrayManager::showWizard);
|
||||||
|
welcomePage->show();
|
||||||
|
}
|
||||||
|
|
||||||
void TrayManager::spawnGetInfoWindow(qint64 evidenceID) {
|
void TrayManager::spawnGetInfoWindow(qint64 evidenceID) {
|
||||||
auto getInfoWindow = new GetInfo(db, evidenceID, this);
|
auto getInfoWindow = new GetInfo(db, evidenceID, this);
|
||||||
connect(getInfoWindow, &GetInfo::evidenceSubmitted, [](const model::Evidence& evi) {
|
connect(getInfoWindow, &GetInfo::evidenceSubmitted, [](const model::Evidence& evi) {
|
||||||
|
@ -252,6 +270,12 @@ void TrayManager::showNoOperationSetTrayMessage() {
|
||||||
void TrayManager::setActiveOperationLabel() {
|
void TrayManager::setActiveOperationLabel() {
|
||||||
const auto& opName = AppConfig::operationName();
|
const auto& opName = AppConfig::operationName();
|
||||||
chooseOpSubmenu->setTitle(tr("Operation: %1").arg(opName.isEmpty() ? tr("<None>") : opName));
|
chooseOpSubmenu->setTitle(tr("Operation: %1").arg(opName.isEmpty() ? tr("<None>") : opName));
|
||||||
|
for(const auto &a : allOperationActions.actions()) {
|
||||||
|
if(a->text() == opName) {
|
||||||
|
a->setChecked(true);
|
||||||
|
selectedAction = a;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrayManager::onOperationListUpdated(bool success,
|
void TrayManager::onOperationListUpdated(bool success,
|
||||||
|
|
|
@ -94,6 +94,12 @@ class TrayManager : public QDialog {
|
||||||
QTimer *updateCheckTimer = nullptr;
|
QTimer *updateCheckTimer = nullptr;
|
||||||
MessageType currentTrayMessage = NO_ACTION;
|
MessageType currentTrayMessage = NO_ACTION;
|
||||||
|
|
||||||
|
///Show the Settings Wizard
|
||||||
|
void showWizard();
|
||||||
|
|
||||||
|
///Show the Welcome Screen
|
||||||
|
void showWelcomeScreen();
|
||||||
|
|
||||||
/// openServicesPath is a variable to store where, on click, to open a path the next time a tray message is displayed
|
/// openServicesPath is a variable to store where, on click, to open a path the next time a tray message is displayed
|
||||||
QString openServicesPath;
|
QString openServicesPath;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue