implement drop file/text/image &&

add import from file option
This commit is contained in:
Nova 2025-10-06 02:25:40 +03:30
parent 930ed61f7e
commit ea73f7d28f
4 changed files with 108 additions and 19 deletions

View File

@ -17,15 +17,15 @@ namespace Configs {
// Amnezia Options // Amnezia Options
bool enable_amnezia = false; bool enable_amnezia = false;
int junk_packet_count; int junk_packet_count = 0;
int junk_packet_min_size; int junk_packet_min_size = 0;
int junk_packet_max_size; int junk_packet_max_size = 0;
int init_packet_junk_size; int init_packet_junk_size = 0;
int response_packet_junk_size; int response_packet_junk_size = 0;
int init_packet_magic_header; int init_packet_magic_header = 0;
int response_packet_magic_header; int response_packet_magic_header = 0;
int underload_packet_magic_header; int underload_packet_magic_header = 0;
int transport_packet_magic_header; int transport_packet_magic_header = 0;
WireguardBean() : AbstractBean(0) { WireguardBean() : AbstractBean(0) {
_add(new configItem("private_key", &privateKey, itemType::string)); _add(new configItem("private_key", &privateKey, itemType::string));

View File

@ -232,10 +232,16 @@ private:
void refresh_table_item(int row, const std::shared_ptr<Configs::ProxyEntity>& profile, bool stopping); void refresh_table_item(int row, const std::shared_ptr<Configs::ProxyEntity>& profile, bool stopping);
void parseQrImage(const QPixmap *image);
void keyPressEvent(QKeyEvent *event) override; void keyPressEvent(QKeyEvent *event) override;
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent* event) override;
// //
void HotkeyEvent(const QString &key); void HotkeyEvent(const QString &key);

View File

@ -557,7 +557,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>800</width> <width>800</width>
<height>17</height> <height>25</height>
</rect> </rect>
</property> </property>
<widget class="QMenu" name="menu_program"> <widget class="QMenu" name="menu_program">
@ -575,6 +575,7 @@
<addaction name="actionHide_window"/> <addaction name="actionHide_window"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="menu_add_from_clipboard2"/> <addaction name="menu_add_from_clipboard2"/>
<addaction name="actionAdd_profile_from_File"/>
<addaction name="menu_scan_qr"/> <addaction name="menu_scan_qr"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionStart_with_system"/> <addaction name="actionStart_with_system"/>
@ -1052,6 +1053,11 @@
<string>Hide window</string> <string>Hide window</string>
</property> </property>
</action> </action>
<action name="actionAdd_profile_from_File">
<property name="text">
<string>Add profile from File</string>
</property>
</action>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget> <customwidget>

View File

@ -49,7 +49,9 @@
#if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0) #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
#include <QStyleHints> #include <QStyleHints>
#endif #endif
#include <QFileDialog>
#include <QToolTip> #include <QToolTip>
#include <QMimeData>
#include <random> #include <random>
#include <3rdparty/QHotkey/qhotkey.h> #include <3rdparty/QHotkey/qhotkey.h>
#include <3rdparty/qv2ray/v2/proxy/QvProxyConfigurator.hpp> #include <3rdparty/qv2ray/v2/proxy/QvProxyConfigurator.hpp>
@ -66,6 +68,7 @@ void UI_InitMainWindow() {
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
mainwindow = this; mainwindow = this;
setAcceptDrops(true);
MW_dialog_message = [=,this](const QString &a, const QString &b) { MW_dialog_message = [=,this](const QString &a, const QString &b) {
runOnUiThread([=,this] runOnUiThread([=,this]
{ {
@ -588,6 +591,25 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
ui->menu_export_config->setVisible(name == software_core_name); ui->menu_export_config->setVisible(name == software_core_name);
ui->menu_export_config->setText(tr("Export %1 config").arg(name)); ui->menu_export_config->setText(tr("Export %1 config").arg(name));
}); });
connect(ui->actionAdd_profile_from_File, &QAction::triggered, this, [=,this]()
{
auto path = QFileDialog::getOpenFileName();
if (path.isEmpty())
{
return;
}
auto file = QFile(path);
if (!file.exists()) return;
if (file.size() > 50 * 1024 * 1024)
{
MW_show_log("File too large, will not process it");
return;
}
file.open(QIODevice::ReadOnly);
auto contents = file.readAll();
file.close();
Subscription::groupUpdater->AsyncUpdate(contents);
});
connect(qApp, &QGuiApplication::commitDataRequest, this, &MainWindow::on_commitDataRequest); connect(qApp, &QGuiApplication::commitDataRequest, this, &MainWindow::on_commitDataRequest);
@ -622,6 +644,55 @@ void MainWindow::closeEvent(QCloseEvent *event) {
} }
} }
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasUrls() || event->mimeData()->hasText()) {
event->acceptProposedAction();
} else {
event->ignore();
}
}
void MainWindow::dropEvent(QDropEvent* event)
{
auto mimeData = event->mimeData();
if (mimeData->hasUrls()) {
QList<QUrl> urlList = mimeData->urls();
for (const QUrl &url : urlList) {
if (url.isLocalFile()) {
if (auto qpx = QPixmap(url.toLocalFile()); !qpx.isNull())
{
parseQrImage(&qpx);
} else if (auto file = QFile(url.toLocalFile()); file.exists())
{
file.open(QFile::ReadOnly);
if (file.size() > 50 * 1024 * 1024)
{
file.close();
MW_show_log("File size is larger than 50MB, will not parse it");
event->acceptProposedAction();
return;
}
auto contents = file.readAll();
file.close();
Subscription::groupUpdater->AsyncUpdate(contents);
}
}
}
event->acceptProposedAction();
return;
}
if (mimeData->hasText()) {
Subscription::groupUpdater->AsyncUpdate(mimeData->text());
event->acceptProposedAction();
return;
}
event->ignore();
}
MainWindow::~MainWindow() { MainWindow::~MainWindow() {
delete ui; delete ui;
} }
@ -1898,6 +1969,19 @@ QPixmap grabScreen(QScreen* screen, bool& ok)
return screen->grabWindow(0, geom.x(), geom.y(), geom.width(), geom.height()); return screen->grabWindow(0, geom.x(), geom.y(), geom.width(), geom.height());
} }
void MainWindow::parseQrImage(const QPixmap *image)
{
const QVector<QString> texts = QrDecoder().decode(image->toImage().convertToFormat(QImage::Format_Grayscale8));
if (texts.isEmpty()) {
MessageBoxInfo(software_name, tr("QR Code not found"));
} else {
for (const QString &text : texts) {
show_log_impl("QR Code Result:\n" + text);
Subscription::groupUpdater->AsyncUpdate(text);
}
}
}
void MainWindow::on_menu_scan_qr_triggered() { void MainWindow::on_menu_scan_qr_triggered() {
hide(); hide();
QThread::sleep(1); QThread::sleep(1);
@ -1907,15 +1991,7 @@ void MainWindow::on_menu_scan_qr_triggered() {
show(); show();
if (ok) { if (ok) {
const QVector<QString> texts = QrDecoder().decode(qpx.toImage().convertToFormat(QImage::Format_Grayscale8)); parseQrImage(&qpx);
if (texts.isEmpty()) {
MessageBoxInfo(software_name, tr("QR Code not found"));
} else {
for (const QString &text : texts) {
show_log_impl("QR Code Result:\n" + text);
Subscription::groupUpdater->AsyncUpdate(text);
}
}
} }
else { else {
MessageBoxInfo(software_name, tr("Unable to capture screen")); MessageBoxInfo(software_name, tr("Unable to capture screen"));
@ -2370,6 +2446,7 @@ void MainWindow::setActionsData()
ui->actionUrl_Test_Group->setData(QString("m21")); ui->actionUrl_Test_Group->setData(QString("m21"));
ui->actionUrl_Test_Selected->setData(QString("m22")); ui->actionUrl_Test_Selected->setData(QString("m22"));
ui->actionHide_window->setData(QString("m23")); ui->actionHide_window->setData(QString("m23"));
ui->actionAdd_profile_from_File->setData(QString("m24"));
} }
QList<QAction*> MainWindow::getActionsForShortcut() QList<QAction*> MainWindow::getActionsForShortcut()