ObsidianDragon - DragonX ImGui Wallet
Full-node GUI wallet for DragonX cryptocurrency. Built with Dear ImGui, SDL3, and OpenGL3/DX11. Features: - Send/receive shielded and transparent transactions - Autoshield with merged transaction display - Built-in CPU mining (xmrig) - Peer management and network monitoring - Wallet encryption with PIN lock - QR code generation for receive addresses - Transaction history with pagination - Console for direct RPC commands - Cross-platform (Linux, Windows)
This commit is contained in:
151
src/ui/windows/qr_popup_dialog.cpp
Normal file
151
src/ui/windows/qr_popup_dialog.cpp
Normal file
@@ -0,0 +1,151 @@
|
||||
// DragonX Wallet - ImGui Edition
|
||||
// Copyright 2024-2026 The Hush Developers
|
||||
// Released under the GPLv3
|
||||
|
||||
#include "qr_popup_dialog.h"
|
||||
#include "../../app.h"
|
||||
#include "../widgets/qr_code.h"
|
||||
#include "../schema/ui_schema.h"
|
||||
#include "../material/draw_helpers.h"
|
||||
#include "../theme.h"
|
||||
#include "../effects/imgui_acrylic.h"
|
||||
#include "imgui.h"
|
||||
|
||||
namespace dragonx {
|
||||
namespace ui {
|
||||
|
||||
// Static member initialization
|
||||
bool QRPopupDialog::s_open = false;
|
||||
std::string QRPopupDialog::s_address;
|
||||
std::string QRPopupDialog::s_label;
|
||||
uintptr_t QRPopupDialog::s_qr_texture = 0;
|
||||
int QRPopupDialog::s_qr_width = 0;
|
||||
int QRPopupDialog::s_qr_height = 0;
|
||||
|
||||
void QRPopupDialog::show(const std::string& address, const std::string& label)
|
||||
{
|
||||
// Cleanup previous texture
|
||||
if (s_qr_texture != 0) {
|
||||
FreeQRTexture(s_qr_texture);
|
||||
s_qr_texture = 0;
|
||||
}
|
||||
|
||||
s_open = true;
|
||||
s_address = address;
|
||||
s_label = label;
|
||||
|
||||
// Generate new QR texture
|
||||
s_qr_texture = GenerateQRTexture(address.c_str(), &s_qr_width, &s_qr_height);
|
||||
}
|
||||
|
||||
bool QRPopupDialog::isOpen()
|
||||
{
|
||||
return s_open;
|
||||
}
|
||||
|
||||
void QRPopupDialog::close()
|
||||
{
|
||||
s_open = false;
|
||||
if (s_qr_texture != 0) {
|
||||
FreeQRTexture(s_qr_texture);
|
||||
s_qr_texture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void QRPopupDialog::render(App* app)
|
||||
{
|
||||
(void)app; // Unused for now
|
||||
|
||||
if (!s_open) return;
|
||||
|
||||
auto& S = schema::UI();
|
||||
auto win = S.window("dialogs.qr-popup");
|
||||
auto qr = S.drawElement("dialogs.qr-popup", "qr-code");
|
||||
auto addrInput = S.input("dialogs.qr-popup", "address-input");
|
||||
auto actionBtn = S.button("dialogs.qr-popup", "action-button");
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(win.width, win.height), ImGuiCond_FirstUseEver);
|
||||
ImVec2 center = ImGui::GetMainViewport()->GetCenter();
|
||||
ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
|
||||
ImGui::SetNextWindowFocus();
|
||||
|
||||
const auto& acrylicTheme = GetCurrentAcrylicTheme();
|
||||
ImGui::OpenPopup("QR Code");
|
||||
if (effects::ImGuiAcrylic::BeginAcrylicPopupModal("QR Code", &s_open, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar, acrylicTheme.popup)) {
|
||||
|
||||
// Label if present
|
||||
if (!s_label.empty()) {
|
||||
ImGui::TextWrapped("%s", s_label.c_str());
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
ImGui::Spacing();
|
||||
}
|
||||
|
||||
// Center the QR code
|
||||
float qr_size = qr.size > 0 ? qr.size : 280;
|
||||
float window_width = ImGui::GetWindowWidth();
|
||||
float padding = (window_width - qr_size) / 2.0f;
|
||||
|
||||
ImGui::SetCursorPosX(padding);
|
||||
|
||||
// Render QR code
|
||||
if (s_qr_texture != 0) {
|
||||
ImGui::Image((ImTextureID)s_qr_texture, ImVec2(qr_size, qr_size));
|
||||
} else {
|
||||
// Fallback: show error
|
||||
ImGui::BeginChild("QRPlaceholder", ImVec2(qr_size, qr_size), true);
|
||||
ImGui::TextWrapped("Failed to generate QR code");
|
||||
ImGui::EndChild();
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::Separator();
|
||||
ImGui::Spacing();
|
||||
|
||||
// Address display
|
||||
ImGui::Text("Address:");
|
||||
|
||||
// Use multiline for z-addresses
|
||||
if (s_address.length() > 50) {
|
||||
char addr_buf[512];
|
||||
strncpy(addr_buf, s_address.c_str(), sizeof(addr_buf) - 1);
|
||||
addr_buf[sizeof(addr_buf) - 1] = '\0';
|
||||
ImGui::InputTextMultiline("##QRAddress", addr_buf, sizeof(addr_buf),
|
||||
ImVec2(-1, addrInput.height > 0 ? addrInput.height : 60), ImGuiInputTextFlags_ReadOnly);
|
||||
} else {
|
||||
char addr_buf[128];
|
||||
strncpy(addr_buf, s_address.c_str(), sizeof(addr_buf) - 1);
|
||||
addr_buf[sizeof(addr_buf) - 1] = '\0';
|
||||
ImGui::SetNextItemWidth(-1);
|
||||
ImGui::InputText("##QRAddress", addr_buf, sizeof(addr_buf), ImGuiInputTextFlags_ReadOnly);
|
||||
}
|
||||
|
||||
ImGui::Spacing();
|
||||
|
||||
// Buttons
|
||||
float button_width = actionBtn.width;
|
||||
float total_width = button_width * 2 + ImGui::GetStyle().ItemSpacing.x;
|
||||
float start_x = (window_width - total_width) / 2.0f;
|
||||
ImGui::SetCursorPosX(start_x);
|
||||
|
||||
if (material::StyledButton("Copy Address", ImVec2(button_width, 0), S.resolveFont(actionBtn.font))) {
|
||||
ImGui::SetClipboardText(s_address.c_str());
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
if (material::StyledButton("Close", ImVec2(button_width, 0), S.resolveFont(actionBtn.font))) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
effects::ImGuiAcrylic::EndAcrylicPopup();
|
||||
|
||||
// Handle window close button
|
||||
if (!s_open && s_qr_texture != 0) {
|
||||
FreeQRTexture(s_qr_texture);
|
||||
s_qr_texture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
} // namespace dragonx
|
||||
Reference in New Issue
Block a user