From d23d3ce1481db24bca54dcc0d93eacb04bc5f25a Mon Sep 17 00:00:00 2001 From: levonpetrosyan93 <45027856+levonpetrosyan93@users.noreply.github.com> Date: Tue, 18 Jun 2024 20:22:22 +0400 Subject: [PATCH 1/4] Increase tx size limit up to 250kb (#1457) * Increase tx size limit up to 250kb * Error messages updated --- src/policy/policy.h | 2 +- src/spark/sparkwallet.cpp | 6 +++--- src/wallet/wallet.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/policy/policy.h b/src/policy/policy.h index 4865201be3..4f211fffbe 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -25,7 +25,7 @@ static const unsigned int DEFAULT_BLOCK_MIN_TX_FEE = 1000; /** The maximum weight for transactions we're willing to relay/mine */ static const unsigned int MAX_STANDARD_TX_WEIGHT = 400000; /** The new maximum weight for transactions we're willing to relay/mine */ -static const unsigned int MAX_NEW_TX_WEIGHT = 520000; +static const unsigned int MAX_NEW_TX_WEIGHT = 1000000; /** Maximum number of signature check operations in an IsStandard() P2SH script */ static const unsigned int MAX_P2SH_SIGOPS = 15; /** The maximum number of sigops we're willing to relay/mine in a single tx */ diff --git a/src/spark/sparkwallet.cpp b/src/spark/sparkwallet.cpp index 0852256861..382cb6c62d 100644 --- a/src/spark/sparkwallet.cpp +++ b/src/spark/sparkwallet.cpp @@ -1023,8 +1023,8 @@ bool CSparkWallet::CreateSparkMintTransactions( // Limit size CTransaction txConst(tx); - if (GetTransactionWeight(txConst) >= MAX_STANDARD_TX_WEIGHT) { - strFailReason = _("Transaction is too large (size limit: 100Kb). Select less inputs or consolidate your UTXOs"); + if (GetTransactionWeight(txConst) >= MAX_NEW_TX_WEIGHT) { + strFailReason = _("Transaction is too large (size limit: 250Kb). Select less inputs or consolidate your UTXOs"); return false; } dPriority = txConst.ComputePriority(dPriority, nBytes); @@ -1536,7 +1536,7 @@ CWalletTx CSparkWallet::CreateSparkSpendTransaction( } if (GetTransactionWeight(tx) >= MAX_NEW_TX_WEIGHT) { - throw std::runtime_error(_("Transaction is too large (size limit: 100Kb). Select less inputs or consolidate your UTXOs")); + throw std::runtime_error(_("Transaction is too large (size limit: 250Kb). Select less inputs or consolidate your UTXOs")); } // check fee diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index b1f5715403..03bc7e6c52 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -4564,9 +4564,9 @@ bool CWallet::CreateTransaction(const std::vector& vecSend, CWalletT nBytes += GetSizeOfCompactSize(nExtraPayloadSize) + nExtraPayloadSize; } - if (GetTransactionWeight(txNew) >= MAX_STANDARD_TX_WEIGHT) { + if (GetTransactionWeight(txNew) >= MAX_NEW_TX_WEIGHT) { // Do not create oversized transactions (bad-txns-oversize). - strFailReason = _("Transaction is too large (size limit: 100Kb). Select less inputs or consolidate your UTXOs"); + strFailReason = _("Transaction is too large (size limit: 250Kb). Select less inputs or consolidate your UTXOs"); return false; } From 327a2b7a97a210c2cb5c6fdfb317bd8e652ba748 Mon Sep 17 00:00:00 2001 From: firstcryptoman <86235719+firstcryptoman@users.noreply.github.com> Date: Tue, 18 Jun 2024 20:22:54 +0400 Subject: [PATCH 2/4] Fix unclickable 'Click here' in migration banner (#1456) --- src/qt/overviewpage.cpp | 36 +++++++++++++++++++++++++++++------- src/qt/overviewpage.h | 4 ++-- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index ea0d1a7b12..1ca4791c45 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -19,6 +19,8 @@ #include "transactiontablemodel.h" #include "walletmodel.h" #include "validation.h" +#include "askpassphrasedialog.h" + #ifdef WIN32 #include @@ -380,14 +382,18 @@ void OverviewPage::onRefreshClicked() { auto privateBalance = walletModel->getLelantusModel()->getPrivateBalance(); auto lGracefulPeriod = ::Params().GetConsensus().nLelantusGracefulPeriod; + int heightDifference = lGracefulPeriod - chainActive.Height(); + const int approxBlocksPerDay = 570; + int daysUntilMigrationCloses = heightDifference / approxBlocksPerDay; + if(privateBalance.first > 0 && chainActive.Height() < lGracefulPeriod && spark::IsSparkAllowed()) { ui->warningFrame->show(); - lelantusGracefulPeriod = QString::fromStdString(std::to_string(lGracefulPeriod)); - currentBlock = QString::fromStdString(std::to_string(chainActive.Height())); + migrationWindowClosesIn = QString::fromStdString(std::to_string(daysUntilMigrationCloses)); + blocksRemaining = QString::fromStdString(std::to_string(heightDifference)); migrateAmount = "" + BitcoinUnits::formatHtmlWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), privateBalance.first); migrateAmount.append(""); - ui->textWarning1->setText(tr("Firo is migrating to Spark. Redemption of coins in Lelantus will be disabled at block %1. Current block is %2.").arg(lelantusGracefulPeriod, currentBlock)); - ui->textWarning2->setText(tr("to migrate %1 from Lelantus.").arg(migrateAmount)); + ui->textWarning1->setText(tr("We have detected Lelantus coins that have not been migrated to Spark. Migration window will close in %1 blocks (~ %2 days).").arg(blocksRemaining , migrationWindowClosesIn)); + ui->textWarning2->setText(tr("to migrate %1 ").arg(migrateAmount)); QFont qFont = ui->migrateButton->font(); qFont.setUnderline(true); ui->migrateButton->setFont(qFont); @@ -398,11 +404,27 @@ void OverviewPage::onRefreshClicked() void OverviewPage::migrateClicked() { - if(walletModel->getAvailableLelantusCoins() && spark::IsSparkAllowed() && chainActive.Height() < ::Params().GetConsensus().nLelantusGracefulPeriod){ - MigrateLelantusToSparkDialog migrate(walletModel); + auto privateBalance = walletModel->getLelantusModel()->getPrivateBalance(); + auto lGracefulPeriod = ::Params().GetConsensus().nLelantusGracefulPeriod; + migrateAmount = "" + BitcoinUnits::formatHtmlWithUnit(walletModel->getOptionsModel()->getDisplayUnit(), privateBalance.first); + migrateAmount.append(""); + QString info = tr("Your wallet needs to be unlocked to migrate your funds to Spark."); + + if(walletModel->getEncryptionStatus() == WalletModel::Locked) { + + AskPassphraseDialog dlg(AskPassphraseDialog::Unlock, this, info); + dlg.setModel(walletModel); + dlg.exec(); + } + if (walletModel->getEncryptionStatus() == WalletModel::Unlocked){ + if(walletModel->getAvailableLelantusCoins() && spark::IsSparkAllowed() && chainActive.Height() < ::Params().GetConsensus().nLelantusGracefulPeriod){ + MigrateLelantusToSparkDialog migrate(walletModel); + if(!migrate.getClickedButton()){ + ui->warningFrame->hide(); + } + } } } - MigrateLelantusToSparkDialog::MigrateLelantusToSparkDialog(WalletModel *_model):QMessageBox() { this->model = _model; diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 3e3e79acd1..84549f2b74 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -86,8 +86,8 @@ public Q_SLOTS: QTimer countDownTimer; int secDelay; - QString lelantusGracefulPeriod; - QString currentBlock; + QString migrationWindowClosesIn; + QString blocksRemaining; QString migrateAmount; private Q_SLOTS: From 290730d29ef7b637e4c289fed0a025d2f11d4571 Mon Sep 17 00:00:00 2001 From: levonpetrosyan93 <45027856+levonpetrosyan93@users.noreply.github.com> Date: Tue, 18 Jun 2024 20:23:50 +0400 Subject: [PATCH 3/4] New rpc calls for mobile (#1449) * Mobile mempool support * getmempooltxids bug fixed * Tx ids with lTags * getmempooltxs rpc interface fixed * Fix getmempooltxs * Review comments applied * Help strings improved --- src/chain.h | 4 ++ src/rpc/client.cpp | 1 + src/rpc/misc.cpp | 161 ++++++++++++++++++++++++++++++++++++++++++++ src/rpc/server.cpp | 4 ++ src/rpc/server.h | 3 + src/spark/state.cpp | 24 ++++++- src/spark/state.h | 5 ++ src/txdb.cpp | 1 + 8 files changed, 202 insertions(+), 1 deletion(-) diff --git a/src/chain.h b/src/chain.h index c6fc34832c..a62f14cb41 100644 --- a/src/chain.h +++ b/src/chain.h @@ -261,6 +261,8 @@ class CBlockIndex sigma::spend_info_container sigmaSpentSerials; std::unordered_map lelantusSpentSerials; std::unordered_map spentLTags; + // linking tag hash mapped to tx hash + std::unordered_map ltagTxhash; //! list of disabling sporks active at this block height //! std::map {feature name} -> {block number when feature is re-enabled again, parameter} @@ -303,6 +305,7 @@ class CBlockIndex sparkMintedCoins.clear(); sparkSetHash.clear(); spentLTags.clear(); + ltagTxhash.clear(); sparkTxHashContext.clear(); sigmaSpentSerials.clear(); lelantusSpentSerials.clear(); @@ -563,6 +566,7 @@ class CDiskBlockIndex : public CBlockIndex if (GetBoolArg("-mobile", false)) { READWRITE(sparkTxHashContext); + READWRITE(ltagTxhash); } } diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp index bfbdf2f22f..629dde9a14 100644 --- a/src/rpc/client.cpp +++ b/src/rpc/client.cpp @@ -194,6 +194,7 @@ static const CRPCConvertParam vRPCConvertParams[] = { "getusedcoinserials", 0 }, { "getlatestcoinids", 0 }, { "getsparkmintmetadata", 0 }, + { "getmempooltxs", 0 }, //Lelantus { "mintspark", 0 }, diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index ad96886540..8f73698fa0 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -1404,6 +1404,63 @@ UniValue getusedcoinstags(const JSONRPCRequest& request) return ret; } +UniValue getusedcoinstagstxhashes(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() != 1) + throw std::runtime_error( + "getusedcoinstagstxhashes\n" + "\nReturns the set of used coin tags paired with tx ids in which it was spent, this rpc required -mobile argument, \n" + "\nArguments:\n" + "{\n" + " \"startNumber \" (int) Number of elements already existing on user side\n" + "}\n" + "\nResult:\n" + "{\n" + " \"tags\" (std::string[]) array of Serialized GroupElements paired with unit256 (tx ids) \n" + "}\n" + ); + + int startNumber; + try { + startNumber = std::stol(request.params[0].get_str()); + } catch (std::logic_error const & e) { + throw std::runtime_error(std::string("An exception occurred while parsing parameters: ") + e.what()); + } + + spark::CSparkState* sparkState = spark::CSparkState::GetState(); + std::unordered_map tags; + std::unordered_map ltagTxhash; + { + LOCK(cs_main); + tags = sparkState->GetSpends(); + ltagTxhash = sparkState->GetSpendTxIds(); + } + UniValue serializedTagsTxIds(UniValue::VARR); + int i = 0; + for ( auto it = tags.begin(); it != tags.end(); ++it, ++i) { + if ((tags.size() - i - 1) < startNumber) + continue; + std::vector serialized; + serialized.resize(34); + it->first.serialize(serialized.data()); + std::vector data; + data.push_back(EncodeBase64(serialized.data(), 34)); + uint256 txid; + uint256 ltagHash = primitives::GetLTagHash(it->first); + if (ltagTxhash.count(ltagHash) > 0) + txid = ltagTxhash[ltagHash]; + data.push_back(EncodeBase64(txid.begin(), txid.size())); + UniValue entity(UniValue::VARR); + entity.push_backV(data); + serializedTagsTxIds.push_back(entity); + } + + UniValue ret(UniValue::VOBJ); + ret.push_back(Pair("tagsandtxids", serializedTagsTxIds)); + + return ret; +} + UniValue getsparklatestcoinid(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 0) @@ -1431,6 +1488,107 @@ UniValue getsparklatestcoinid(const JSONRPCRequest& request) return UniValue(latestCoinId); } +UniValue getmempoolsparktxids(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() != 0) + throw std::runtime_error( + "getmempoolsparktxids\n" + "\nReturns spark transaction ids existing in the mempool.\n" + ); + + UniValue result(UniValue::VARR); + std::vector txs = mempool.infoAll(); + for (auto it = txs.begin(); it != txs.end(); it++) { + if (!it->tx->IsSparkTransaction()) + continue; + result.push_back(EncodeBase64(it->tx->GetHash().begin(), it->tx->GetHash().size())); + } + + return result; +} + +UniValue getmempoolsparktxs(const JSONRPCRequest& request) +{ + if (request.fHelp || request.params.size() != 1) + throw std::runtime_error( + "getmempoolsparktxs\n" + "\nReturns spark metadata for each transaction id, in case tx already was removed from mempool, nothing will be returned for specific id.\n" + "\nArguments:\n" + " \"txids\"\n" + " [\n" + " {\n" + " \"txid\" (string) The transaction hash\n" + " }\n" + " ,...\n" + " ]\n" + "\nResult:\n" + "txid , {\n" + " \"lTags\" Array of GroupElements, or a string 'MintTX' in case it is mint tx\n" + " \"serial_context\" byte array which is used to identify the output spark coins, it is unique for each ix\n" + " \"coins\" Array of serialized spar::Coin elements, the output coins of the tx\n" + "}\n" + + HelpExampleCli("getmempoolsparktxs", "'{\"txids\": [\"b476ed2b374bb081ea51d111f68f0136252521214e213d119b8dc67b92f5a390\",\"b476ed2b374bb081ea51d111f68f0136252521214e213d119b8dc67b92f5a390\"]}'") + + HelpExampleRpc("getmempoolsparktxs", "{\"txids\": [\"b476ed2b374bb081ea51d111f68f0136252521214e213d119b8dc67b92f5a390\",\"b476ed2b374bb081ea51d111f68f0136252521214e213d119b8dc67b92f5a390\"]}") + + ); + + UniValue txids = find_value(request.params[0].get_obj(), "txids"); + + UniValue result(UniValue::VOBJ); + for(UniValue const & element : txids.getValues()){ + uint256 txid; + txid.SetHex(element.get_str()); + CTransactionRef tx = mempool.get(txid); + if (tx == nullptr || !tx->IsSparkTransaction()) + continue; + + UniValue data(UniValue::VOBJ); + std::vector lTags_; + UniValue lTags_json(UniValue::VARR); + if (tx->IsSparkSpend()) + { + try { + spark::SpendTransaction spend = spark::ParseSparkSpend(*tx); + auto lTags = spend.getUsedLTags(); + for ( auto it = lTags.begin(); it != lTags.end(); ++it) { + std::vector serialized; + serialized.resize(34); + it->serialize(serialized.data()); + lTags_.push_back(EncodeBase64(serialized.data(), 34)); + } + } catch (const std::exception &) { + continue; + } + } else { + lTags_.push_back("MintTX"); + } + lTags_json.push_backV(lTags_); + + data.push_back(Pair("lTags ", lTags_json)); // Spend lTags for corresponding tx, + + std::vector serial_context = spark::getSerialContext(*tx); + UniValue serial_context_json(UniValue::VARR); + serial_context_json.push_back(EncodeBase64(serial_context.data(), serial_context.size())); + data.push_back(Pair("serial_context", serial_context_json)); // spark serial context + + std::vector coins = spark::GetSparkMintCoins(*tx); + std::vector serialized_coins; + UniValue serialized_json(UniValue::VARR); + for (auto& coin: coins) { + CDataStream serializedCoin(SER_NETWORK, PROTOCOL_VERSION); + serializedCoin << coin; + std::vector vch(serializedCoin.begin(), serializedCoin.end()); + serialized_coins.push_back(EncodeBase64(vch.data(), size_t(vch.size()))); // coi + } + serialized_json.push_backV(serialized_coins); + data.push_back(Pair("coins", serialized_json)); + + result.push_back(Pair(EncodeBase64(txid.begin(), txid.size()), data)); + } + + return result; +} + UniValue checkifmncollateral(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 2) @@ -1762,7 +1920,10 @@ static const CRPCCommand commands[] = { "mobile", "getsparkanonymityset", &getsparkanonymityset, false }, { "mobile", "getsparkmintmetadata", &getsparkmintmetadata, true }, { "mobile", "getusedcoinstags", &getusedcoinstags, false }, + { "mobile", "getusedcoinstagstxhashes", &getusedcoinstagstxhashes, false }, { "mobile", "getsparklatestcoinid", &getsparklatestcoinid, true }, + { "mobile", "getmempoolsparktxids", &getmempoolsparktxids, true }, + { "mobile", "getmempoolsparktxs", &getmempoolsparktxs, true }, { "mobile", "checkifmncollateral", &checkifmncollateral, false }, diff --git a/src/rpc/server.cpp b/src/rpc/server.cpp index 04870a06bc..0f07787f1b 100644 --- a/src/rpc/server.cpp +++ b/src/rpc/server.cpp @@ -342,7 +342,11 @@ static const CRPCCommand vRPCCommands[] = { "mobile", "getsparkanonymityset", &getsparkanonymityset, false }, { "mobile", "getsparkmintmetadata", &getsparkmintmetadata, true }, { "mobile", "getusedcoinstags", &getusedcoinstags, false }, + { "mobile", "getusedcoinstagstxhashes", &getusedcoinstagstxhashes, false }, { "mobile", "getsparklatestcoinid", &getsparklatestcoinid, true }, + { "mobile", "getmempoolsparktxids", &getmempoolsparktxids, true }, + { "mobile", "getmempoolsparktxs", &getmempoolsparktxs, true }, + { "mobile", "checkifmncollateral", &checkifmncollateral, false }, diff --git a/src/rpc/server.h b/src/rpc/server.h index b16f0f4e95..dbf98839b9 100644 --- a/src/rpc/server.h +++ b/src/rpc/server.h @@ -216,7 +216,10 @@ extern UniValue getlatestcoinid(const JSONRPCRequest& params); extern UniValue getsparkanonymityset(const JSONRPCRequest& params); extern UniValue getsparkmintmetadata(const JSONRPCRequest& params); extern UniValue getusedcoinstags(const JSONRPCRequest& params); +extern UniValue getusedcoinstagstxhashes(const JSONRPCRequest& params); extern UniValue getsparklatestcoinid(const JSONRPCRequest& params); +extern UniValue getmempoolsparktxids(const JSONRPCRequest& params); +extern UniValue getmempoolsparktxs(const JSONRPCRequest& params); extern UniValue checkifmncollateral(const JSONRPCRequest& params); diff --git a/src/spark/state.cpp b/src/spark/state.cpp index 5359a7a9a0..4eebb613e4 100644 --- a/src/spark/state.cpp +++ b/src/spark/state.cpp @@ -265,10 +265,16 @@ bool ConnectBlockSpark( } if (!fJustCheck) { - BOOST_FOREACH(auto& lTag, pblock->sparkTxInfo->spentLTags) { + BOOST_FOREACH (auto& lTag, pblock->sparkTxInfo->spentLTags) { pindexNew->spentLTags.insert(lTag); sparkState.AddSpend(lTag.first, lTag.second); } + if (GetBoolArg("-mobile", false)) { + BOOST_FOREACH (auto& lTag, pblock->sparkTxInfo->ltagTxhash) { + pindexNew->ltagTxhash.insert(lTag); + sparkState.AddLTagTxHash(lTag.first, lTag.second); + } + } } else { return true; @@ -693,6 +699,9 @@ bool CheckSparkSpendTransaction( if (sparkTxInfo && !sparkTxInfo->fInfoIsComplete) { for (size_t i = 0; i < lTags.size(); i++) { sparkTxInfo->spentLTags.insert(std::make_pair(lTags[i], ids[i])); + if (GetBoolArg("-mobile", false)) { + sparkTxInfo->ltagTxhash.insert(std::make_pair(primitives::GetLTagHash(lTags[i]), hashTx)); + } } } } @@ -1038,6 +1047,10 @@ void CSparkState::AddSpend(const GroupElement& lTag, int coinGroupId) { } } +void CSparkState::AddLTagTxHash(const uint256& lTagHash, const uint256& txHash) { + ltagTxhash[lTagHash] = txHash; +} + void CSparkState::RemoveSpend(const GroupElement& lTag) { auto iter = usedLTags.find(lTag); if (iter != usedLTags.end()) { @@ -1074,6 +1087,11 @@ void CSparkState::AddBlock(CBlockIndex *index) { for (auto const &lTags : index->spentLTags) { AddSpend(lTags.first, lTags.second); } + if (GetBoolArg("-mobile", false)) { + for (auto const &elem : index->ltagTxhash) { + AddLTagTxHash(elem.first, elem.second); + } + } } void CSparkState::RemoveBlock(CBlockIndex *index) { @@ -1320,6 +1338,10 @@ std::unordered_map const & CSparkState::Get return usedLTags; } +std::unordered_map const& CSparkState::GetSpendTxIds() const { + return ltagTxhash; +} + std::unordered_map const& CSparkState::GetCoinGroups() const { return coinGroups; } diff --git a/src/spark/state.h b/src/spark/state.h index 3820cb1a1d..c8883875ef 100644 --- a/src/spark/state.h +++ b/src/spark/state.h @@ -26,6 +26,7 @@ class CSparkTxInfo { // linking tag for every spend (map from lTag to coin group id) std::unordered_map spentLTags; + std::unordered_map ltagTxhash; // information about transactions in the block is complete bool fInfoIsComplete; @@ -168,6 +169,7 @@ class CSparkState { void AddMintsToStateAndBlockIndex(CBlockIndex *index, const CBlock* pblock); void AddSpend(const GroupElement& lTag, int coinGroupId); + void AddLTagTxHash(const uint256& lTagHash, const uint256& txHash); void RemoveSpend(const GroupElement& lTag); // Add everything from the block to the state void AddBlock(CBlockIndex *index); @@ -213,6 +215,7 @@ class CSparkState { std::unordered_map const & GetMints() const; std::unordered_map const & GetSpends() const; + std::unordered_map const& GetSpendTxIds() const; std::unordered_map const & GetCoinGroups() const; std::unordered_map const & GetMempoolLTags() const; @@ -238,6 +241,8 @@ class CSparkState { std::unordered_map mintedCoins; // Set of all used coin linking tags. std::unordered_map usedLTags; + // linking tag hash mapped to tx hash + std::unordered_map ltagTxhash; typedef std::map metainfo_container_t; metainfo_container_t extendedMintMetaInfo, mintMetaInfo, spendMetaInfo; diff --git a/src/txdb.cpp b/src/txdb.cpp index acb6463381..2ba448dffa 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -425,6 +425,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts(boost::functionsparkSetHash = diskindex.sparkSetHash; pindexNew->spentLTags = diskindex.spentLTags; pindexNew->sparkTxHashContext = diskindex.sparkTxHashContext; + pindexNew->ltagTxhash = diskindex.ltagTxhash; pindexNew->activeDisablingSporks = diskindex.activeDisablingSporks; From fa6a50cc36eab7239632c3e7c0cfa8ce09a35e9c Mon Sep 17 00:00:00 2001 From: firstcryptoman <86235719+firstcryptoman@users.noreply.github.com> Date: Tue, 18 Jun 2024 20:24:21 +0400 Subject: [PATCH 4/4] Qt scaling fix (#1437) * Implement qt scaling fixes * Adjust toolbar widget sizes dynamically * Adjust component sizing dynamically on Masternode and Transaction pages. * Adjust instantsendWidget width to be dynamic in TransactionView * Bug fixes and dynamic text scaling * Enhance UI scalability by adding dynamic text resizing across various pages * Update font size and set minimum label width for readability. * Update dynamic scaling --- src/qt/bitcoingui.cpp | 27 ++++++++- src/qt/bitcoingui.h | 6 +- src/qt/masternodelist.cpp | 45 +++++++++++++++ src/qt/masternodelist.h | 4 +- src/qt/overviewpage.cpp | 100 ++++++++++++++++++++++++++++++++++ src/qt/overviewpage.h | 5 +- src/qt/receivecoinsdialog.cpp | 95 ++++++++++++++++++++++++++++++++ src/qt/receivecoinsdialog.h | 6 +- src/qt/sendcoinsdialog.cpp | 86 ++++++++++++++++++++++++++++- src/qt/sendcoinsdialog.h | 3 + src/qt/sendcoinsentry.cpp | 39 +++++++++++++ src/qt/sendcoinsentry.h | 3 + src/qt/transactionview.cpp | 62 ++++++++++++++++++++- src/qt/transactionview.h | 3 + 14 files changed, 475 insertions(+), 9 deletions(-) diff --git a/src/qt/bitcoingui.cpp b/src/qt/bitcoingui.cpp index bad8afeb82..b07dbbfe66 100644 --- a/src/qt/bitcoingui.cpp +++ b/src/qt/bitcoingui.cpp @@ -510,7 +510,7 @@ void BitcoinGUI::createToolBars() { if(walletFrame) { - QToolBar *toolbar = addToolBar(tr("Tabs toolbar")); + toolbar = addToolBar(tr("Tabs toolbar")); toolbar->setContextMenuPolicy(Qt::PreventContextMenu); toolbar->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); toolbar->setToolButtonStyle(Qt::ToolButtonTextOnly); @@ -523,7 +523,7 @@ void BitcoinGUI::createToolBars() toolbar->addAction(lelantusAction); toolbar->addAction(masternodeAction); - QLabel *logoLabel = new QLabel(); + logoLabel = new QLabel(); logoLabel->setObjectName("lblToolbarLogo"); logoLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); @@ -1474,3 +1474,26 @@ void UnitDisplayStatusBarControl::onMenuSelection(QAction* action) optionsModel->setDisplayUnit(action->data()); } } + +// Handles resize events for the BitcoinGUI widget by adjusting internal component sizes. +void BitcoinGUI::resizeEvent(QResizeEvent* event) { + QMainWindow::resizeEvent(event); + + // Retrieve new dimensions from the resize event + int newWidth = event->size().width(); + int newHeight = event->size().height(); + int actionWidth = newWidth / 6; + + // Set widths for each action dynamically + QWidget* overviewWidget = toolbar->widgetForAction(overviewAction); + QWidget* receiveWidget = toolbar->widgetForAction(receiveCoinsAction); + QWidget* historyWidget = toolbar->widgetForAction(historyAction); + QWidget* sendCoinsWidget = toolbar->widgetForAction(sendCoinsAction); + QWidget* masternodeWidget = toolbar->widgetForAction(masternodeAction); + + overviewWidget->setMinimumWidth(actionWidth); + receiveWidget->setMinimumWidth(actionWidth); + historyWidget->setMinimumWidth(actionWidth); + sendCoinsWidget->setMinimumWidth(actionWidth); + masternodeWidget->setMinimumWidth(actionWidth); +} \ No newline at end of file diff --git a/src/qt/bitcoingui.h b/src/qt/bitcoingui.h index a2e6b1c5fd..bb2db20668 100644 --- a/src/qt/bitcoingui.h +++ b/src/qt/bitcoingui.h @@ -17,6 +17,8 @@ #include #include #include +#include +#include class ClientModel; class NetworkStyle; @@ -121,7 +123,8 @@ class BitcoinGUI : public QMainWindow QAction *lelantusAction; QAction *masternodeAction; QAction *logoAction; - + QToolBar *toolbar; + QLabel *logoLabel; QSystemTrayIcon *trayIcon; QMenu *trayIconMenu; Notificator *notificator; @@ -141,6 +144,7 @@ class BitcoinGUI : public QMainWindow void createMenuBar(); /** Create the toolbars */ void createToolBars(); + void resizeEvent(QResizeEvent*); /** Create system tray icon and notification */ void createTrayIcon(const NetworkStyle *networkStyle); /** Create system tray menu (or setup the dock menu) */ diff --git a/src/qt/masternodelist.cpp b/src/qt/masternodelist.cpp index a5b5e399e0..906b924326 100644 --- a/src/qt/masternodelist.cpp +++ b/src/qt/masternodelist.cpp @@ -367,3 +367,48 @@ void MasternodeList::copyCollateralOutpoint_clicked() QApplication::clipboard()->setText(QString::fromStdString(dmn->collateralOutpoint.ToStringShort())); } + +void MasternodeList::resizeEvent(QResizeEvent* event) +{ + QWidget::resizeEvent(event); + + const int newWidth = event->size().width(); + const int newHeight = event->size().height(); + + adjustTextSize(newWidth ,newHeight); + + // Calculate new column widths based on the new window width + int newWidthOwner = static_cast(newWidth * 0.19); + int newWidthMin = static_cast(newWidth * 0.08); + int newWidthMid = static_cast(newWidth * 0.12); + int newWidthStatus = static_cast(newWidth * 0.11); + + // Apply new column widths + ui->tableWidgetMasternodesDIP3->setColumnWidth(0, newWidthStatus); + ui->tableWidgetMasternodesDIP3->setColumnWidth(1, newWidthMin); + ui->tableWidgetMasternodesDIP3->setColumnWidth(2, newWidthMin); + ui->tableWidgetMasternodesDIP3->setColumnWidth(3, newWidthMid); + ui->tableWidgetMasternodesDIP3->setColumnWidth(4, newWidthMid); + ui->tableWidgetMasternodesDIP3->setColumnWidth(5, newWidthMid); + ui->tableWidgetMasternodesDIP3->setColumnWidth(6, newWidthMid); + ui->tableWidgetMasternodesDIP3->setColumnWidth(7, newWidthMid); + ui->tableWidgetMasternodesDIP3->setColumnWidth(8, newWidthMid); + ui->tableWidgetMasternodesDIP3->setColumnWidth(9, newWidthOwner); +} +void MasternodeList::adjustTextSize(int width,int height){ + + const double fontSizeScalingFactor = 70.0; + int baseFontSize = std::min(width, height) / fontSizeScalingFactor; + int fontSize = std::min(15, std::max(12, baseFontSize)); + QFont font = this->font(); + font.setPointSize(fontSize); + + // Set font size for all labels + ui->label_filter_2->setFont(font); + ui->label_count_2->setFont(font); + ui->countLabelDIP3->setFont(font); + ui->checkBoxMyMasternodesOnly->setFont(font); + ui->tableWidgetMasternodesDIP3->setFont(font); + ui->tableWidgetMasternodesDIP3->horizontalHeader()->setFont(font); + ui->tableWidgetMasternodesDIP3->verticalHeader()->setFont(font); +} \ No newline at end of file diff --git a/src/qt/masternodelist.h b/src/qt/masternodelist.h index 58fec5d426..6d469ea9be 100644 --- a/src/qt/masternodelist.h +++ b/src/qt/masternodelist.h @@ -11,6 +11,7 @@ #include #include #include +#include #define MASTERNODELIST_UPDATE_SECONDS 3 #define MASTERNODELIST_FILTER_COOLDOWN_SECONDS 3 @@ -38,7 +39,8 @@ class MasternodeList : public QWidget void setClientModel(ClientModel* clientModel); void setWalletModel(WalletModel* walletModel); - + void resizeEvent(QResizeEvent*) override; + void adjustTextSize(int width,int height); private: QMenu* contextMenuDIP3; int64_t nTimeFilterUpdatedDIP3; diff --git a/src/qt/overviewpage.cpp b/src/qt/overviewpage.cpp index 1ca4791c45..507f7f604d 100644 --- a/src/qt/overviewpage.cpp +++ b/src/qt/overviewpage.cpp @@ -497,4 +497,104 @@ void MigrateLelantusToSparkDialog::onMigrateClicked() bool MigrateLelantusToSparkDialog::getClickedButton() { return clickedButton; +} +void OverviewPage::resizeEvent(QResizeEvent* event) +{ + QWidget::resizeEvent(event); + + // Retrieve new dimensions from the resize event + const int newWidth = event->size().width(); + const int newHeight = event->size().height(); + adjustTextSize(newWidth, newHeight); + + // Determine widths for specific widgets as percentages of total width + int labelWidth = static_cast(newWidth * 0.5); + int labelMinWidth = static_cast(newWidth * 0.15); + int labelMaxWidth = static_cast(newWidth * 0.35); + const int labelHeight = 20; + + // Configure the dimensions and constraints of each widget + ui->labelBalance->setFixedWidth(labelWidth); + ui->labelBalance->setMinimumWidth(labelMinWidth); + ui->labelBalance->setMaximumWidth(labelMaxWidth); + ui->labelBalance->setFixedHeight(labelHeight); + + ui->labelUnconfirmed->setFixedWidth(labelWidth); + ui->labelUnconfirmed->setMinimumWidth(labelMinWidth); + ui->labelUnconfirmed->setMaximumWidth(labelMaxWidth); + ui->labelUnconfirmed->setFixedHeight(labelHeight); + + int buttonWidth = static_cast(newWidth * 0.15); + int buttonHeight = static_cast(newHeight * 0.05); + int buttonMinHeight = static_cast(20); + int buttonMaxHeight = static_cast(45); + + ui->anonymizeButton->setMinimumWidth(buttonWidth); + ui->anonymizeButton->setMaximumWidth(buttonWidth * 2); + ui->anonymizeButton->setMinimumHeight(buttonMinHeight); + ui->anonymizeButton->setMaximumHeight(buttonMaxHeight); + + // Set the minimum width for all label widgets to ensure they maintain a consistent and readable size regardless of window resizing + ui->labelAnonymizable->setMinimumWidth(labelMinWidth); + ui->labelAlerts->setMinimumWidth(labelMinWidth); + ui->label->setMinimumWidth(labelMinWidth); + ui->labelWatchPending->setMinimumWidth(labelMinWidth); + ui->labelBalance->setMinimumWidth(labelMinWidth); + ui->labelSpendable->setMinimumWidth(labelMinWidth); + ui->labelWatchAvailable->setMinimumWidth(labelMinWidth); + ui->labelUnconfirmedPrivate->setMinimumWidth(labelMinWidth); + ui->labelWatchonly->setMinimumWidth(labelMinWidth); + ui->labelTotal->setMinimumWidth(labelMinWidth); + ui->labelWatchTotal->setMinimumWidth(labelMinWidth); + ui->labelUnconfirmed->setMinimumWidth(labelMinWidth); + ui->labelImmature->setMinimumWidth(labelMinWidth); + ui->labelPrivate->setMinimumWidth(labelMinWidth); + ui->label_4->setMinimumWidth(labelMinWidth); +} +void OverviewPage::adjustTextSize(int width, int height){ + + const double fontSizeScalingFactor = 133.0; + int baseFontSize = width / fontSizeScalingFactor; + int fontSize = std::min(15, std::max(12, baseFontSize)); + + // Font for regular text components(not bold) + QFont textFont = ui->labelBalance->font(); + textFont.setPointSize(fontSize); + textFont.setBold(false); + + // Font for text components that should be bold + QFont labelFont = textFont; + labelFont.setBold(true); + + ui->textWarning1->setFont(textFont); + ui->textWarning2->setFont(textFont); + ui->labelWalletStatus->setFont(textFont); + ui->anonymizeButton->setFont(textFont); + + // Apply label font to all label components + ui->labelAlerts->setFont(labelFont); + ui->label_5->setFont(labelFont); + ui->labelAnonymizableText->setFont(textFont); + ui->label->setFont(labelFont); + ui->labelAnonymizable->setFont(labelFont); + ui->labelWatchPending->setFont(labelFont); + ui->labelBalance->setFont(labelFont); + ui->labelSpendable->setFont(labelFont); + ui->labelWatchAvailable->setFont(labelFont); + ui->labelPendingText->setFont(textFont); + ui->labelUnconfirmedPrivate->setFont(labelFont); + ui->labelUnconfirmedPrivateText->setFont(textFont); + ui->labelTotalText->setFont(textFont); + ui->labelWatchonly->setFont(labelFont); + ui->labelBalanceText->setFont(textFont); + ui->labelTotal->setFont(labelFont); + ui->labelWatchTotal->setFont(labelFont); + ui->labelUnconfirmed->setFont(labelFont); + ui->labelImmatureText->setFont(textFont); + ui->labelImmature->setFont(labelFont); + ui->labelWatchImmature->setFont(labelFont); + ui->labelPrivateText->setFont(textFont); + ui->labelPrivate->setFont(labelFont); + ui->label_4->setFont(labelFont); + } \ No newline at end of file diff --git a/src/qt/overviewpage.h b/src/qt/overviewpage.h index 84549f2b74..53a75aa594 100644 --- a/src/qt/overviewpage.h +++ b/src/qt/overviewpage.h @@ -16,6 +16,8 @@ #include #include #include +#include + class ClientModel; class TransactionFilterProxy; @@ -44,6 +46,7 @@ class OverviewPage : public QWidget void setWalletModel(WalletModel *walletModel); void showOutOfSyncWarning(bool fShow); void UpdatePropertyBalance(unsigned int propertyId, uint64_t available, uint64_t reserved); + void resizeEvent(QResizeEvent* event) override; public Q_SLOTS: void on_anonymizeButton_clicked(); @@ -89,7 +92,7 @@ public Q_SLOTS: QString migrationWindowClosesIn; QString blocksRemaining; QString migrateAmount; - + void adjustTextSize(int width,int height); private Q_SLOTS: void updateDisplayUnit(); void handleTransactionClicked(const QModelIndex &index); diff --git a/src/qt/receivecoinsdialog.cpp b/src/qt/receivecoinsdialog.cpp index 963a11f4dd..21b9352591 100644 --- a/src/qt/receivecoinsdialog.cpp +++ b/src/qt/receivecoinsdialog.cpp @@ -24,6 +24,7 @@ #include #include #include +#include ReceiveCoinsDialog::ReceiveCoinsDialog(const PlatformStyle *_platformStyle, QWidget *parent) : QDialog(parent), @@ -360,4 +361,98 @@ void RecentRequestsFilterProxy::setTypeFilter(quint32 modes) { this->typeFilter = modes; invalidateFilter(); +} + +// Handles resize events for the ReceiveCoinsDialog widget by adjusting internal component sizes. +void ReceiveCoinsDialog::resizeEvent(QResizeEvent* event) +{ + QDialog::resizeEvent(event); + + // Get new size from the event + const int newWidth = event->size().width(); + const int newHeight = event->size().height(); + + adjustTextSize(newWidth,newHeight); + // Set fixed, minimum, and maximum sizes for ComboBoxes + int comboBoxMinHeight = 20; + int comboBoxMaxHeight = 40; + int comboBoxWidth = newWidth * 0.08; + int comboBoxMinWidth = newWidth * 0.05; + int comboBoxMaxWidth = newWidth * 0.1; + + ui->addressTypeCombobox->setMinimumWidth(comboBoxMinWidth); + ui->addressTypeCombobox->setMaximumWidth(comboBoxMaxWidth); + ui->addressTypeCombobox->setMinimumHeight(comboBoxMinHeight); + ui->addressTypeCombobox->setMaximumHeight(comboBoxMaxHeight); + + ui->addressTypeHistoryCombobox->setMinimumWidth(comboBoxMinWidth); + ui->addressTypeHistoryCombobox->setMaximumWidth(comboBoxMaxWidth); + ui->addressTypeHistoryCombobox->setMinimumHeight(comboBoxMinHeight); + ui->addressTypeHistoryCombobox->setMaximumHeight(comboBoxMaxHeight); + + // Set sizes for buttons dynamically + int buttonMinHeight = 20; + int buttonMaxHeight = 35; + int buttonWidth = newWidth * 0.15; + int buttonMinWidth = newWidth * 0.1; + int buttonMaxWidth = newWidth * 0.4; + + ui->clearButton->setMinimumWidth(buttonMinWidth); + ui->clearButton->setMaximumWidth(buttonMaxWidth); + ui->clearButton->setMinimumHeight(buttonMinHeight); + ui->clearButton->setMaximumHeight(buttonMaxHeight); + + ui->receiveButton->setMinimumWidth(buttonMinWidth); + ui->receiveButton->setMaximumWidth(buttonMaxWidth); + ui->receiveButton->setMinimumHeight(buttonMinHeight); + ui->receiveButton->setMaximumHeight(buttonMaxHeight); + + ui->showRequestButton->setMinimumWidth(buttonMinWidth); + ui->showRequestButton->setMaximumWidth(buttonMaxWidth); + ui->showRequestButton->setMinimumHeight(buttonMinHeight); + ui->showRequestButton->setMaximumHeight(buttonMaxHeight); + + ui->removeRequestButton->setMinimumWidth(buttonMinWidth); + ui->removeRequestButton->setMaximumWidth(buttonMaxWidth); + ui->removeRequestButton->setMinimumHeight(buttonMinHeight); + ui->removeRequestButton->setMaximumHeight(buttonMaxHeight); + + // Adjust column widths proportionally + int dateColumnWidth = newWidth * 0.25; + int labelColumnWidth = newWidth * 0.25; + int addressTypeColumnWidth = newWidth * 0.25; + int amountColumnWidth = newWidth * 0.25; + + ui->recentRequestsView->setColumnWidth(RecentRequestsTableModel::Date, dateColumnWidth); + ui->recentRequestsView->setColumnWidth(RecentRequestsTableModel::Label, labelColumnWidth); + ui->recentRequestsView->setColumnWidth(RecentRequestsTableModel::AddressType, addressTypeColumnWidth); + ui->recentRequestsView->setColumnWidth(RecentRequestsTableModel::Amount, amountColumnWidth); +} +void ReceiveCoinsDialog::adjustTextSize(int width,int height){ + + const double fontSizeScalingFactor = 70.0; + int baseFontSize = std::min(width, height) / fontSizeScalingFactor; + int fontSize = std::min(15, std::max(12, baseFontSize)); + QFont font = this->font(); + font.setPointSize(fontSize); + + // Set font size for all labels + ui->reuseAddress->setFont(font); + ui->label_4->setFont(font); + ui->label_3->setFont(font); + ui->addressTypeLabel->setFont(font); + ui->label_5->setFont(font); + ui->label_2->setFont(font); + ui->label->setFont(font); + ui->label_7->setFont(font); + ui->label_6->setFont(font); + ui->receiveButton->setFont(font); + ui->clearButton->setFont(font); + ui->showRequestButton->setFont(font); + ui->removeRequestButton->setFont(font); + ui->addressTypeCombobox->setFont(font); + ui->addressTypeHistoryCombobox->setFont(font); + ui->recentRequestsView->setFont(font); + ui->recentRequestsView->horizontalHeader()->setFont(font); + ui->recentRequestsView->verticalHeader()->setFont(font); } \ No newline at end of file diff --git a/src/qt/receivecoinsdialog.h b/src/qt/receivecoinsdialog.h index 47dc5e992a..c5eac0b986 100644 --- a/src/qt/receivecoinsdialog.h +++ b/src/qt/receivecoinsdialog.h @@ -15,6 +15,7 @@ #include #include #include +#include class OptionsModel; class PlatformStyle; @@ -57,7 +58,8 @@ class ReceiveCoinsDialog : public QDialog ~ReceiveCoinsDialog(); void setModel(WalletModel *model); - + + void resizeEvent(QResizeEvent* event) override; public Q_SLOTS: void clear(); void reject(); @@ -77,7 +79,7 @@ public Q_SLOTS: QModelIndex selectedRow(); void copyColumnToClipboard(int column); RecentRequestsFilterProxy *recentRequestsProxyModel; - + void adjustTextSize(int width,int height); private Q_SLOTS: void on_receiveButton_clicked(); void on_showRequestButton_clicked(); diff --git a/src/qt/sendcoinsdialog.cpp b/src/qt/sendcoinsdialog.cpp index 66b380fea5..26cbf138e5 100644 --- a/src/qt/sendcoinsdialog.cpp +++ b/src/qt/sendcoinsdialog.cpp @@ -1403,4 +1403,88 @@ void SendGoPrivateDialog::onGoPrivateClicked() bool SendGoPrivateDialog::getClickedButton() { return clickedButton; -} \ No newline at end of file +} +void SendCoinsDialog::resizeEvent(QResizeEvent* event) { + QWidget::resizeEvent(event); + + // Retrieve new dimensions from the resize event + const int newWidth = event->size().width(); + const int newHeight = event->size().height(); + + const int labelMinWidth = static_cast(newWidth * 0.15); + + // Resize and adjust components + ui->sendButton->setMinimumWidth(labelMinWidth); + ui->clearButton->setMinimumWidth(labelMinWidth); + ui->addButton->setMinimumWidth(labelMinWidth); + ui->buttonChooseFee->setMinimumWidth(labelMinWidth); + ui->buttonMinimizeFee->setMinimumWidth(labelMinWidth); + ui->switchFundButton->setMinimumWidth(labelMinWidth); + ui->pushButtonCoinControl->setMinimumWidth(labelMinWidth); + + + // Dynamically adjust text sizes based on the new dimensions + adjustTextSize(newWidth, newHeight); +} + +void SendCoinsDialog::adjustTextSize(int width, int height) { + const double fontSizeScalingFactor = 131.3; + int baseFontSize = width / fontSizeScalingFactor; + int fontSize = std::min(15, std::max(12, baseFontSize)); + + QFont font = ui->labelBalance->font(); + font.setPointSize(fontSize); + + QFont textFont = font; + textFont.setBold(true); + + // Set font size for all labels + ui->labelBalance->setFont(font); + ui->lineEditCoinControlChange->setFont(font); + ui->labelFeeEstimation->setFont(font); + ui->labelFeeHeadline->setFont(font); + ui->labelCoinControlFeatures->setFont(textFont); + ui->labelCoinControlAutomaticallySelected->setFont(font); + ui->labelCoinControlInsuffFunds->setFont(font); + ui->labelCoinControlQuantity->setFont(font); + ui->labelCoinControlBytes->setFont(font); + ui->labelCoinControlAmount->setFont(font); + ui->labelCoinControlLowOutput->setFont(font); + ui->labelCoinControlFee->setFont(font); + ui->labelCoinControlAfterFee->setFont(font); + ui->labelCoinControlChange->setFont(font); + ui->labelFeeMinimized->setFont(font); + ui->labelBalance->setFont(font); + ui->radioSmartFee->setFont(font); + ui->radioCustomPerKilobyte->setFont(font); + ui->radioCustomFee->setFont(font); + ui->radioCustomAtLeast->setFont(font); + ui->labelBalanceText->setFont(font); + ui->labelFeeEstimation->setFont(font); + ui->labelSmartFee->setFont(font); + ui->labelSmartFee2->setFont(font); + ui->labelSmartFee3->setFont(font); + ui->labelSmartFeeNormal->setFont(font); + ui->labelSmartFeeFast->setFont(font); + ui->labelCoinControlQuantityText->setFont(font); + ui->labelCoinControlBytesText->setFont(font); + ui->labelCoinControlAmountText->setFont(font); + ui->labelCoinControlLowOutputText->setFont(font); + ui->labelCoinControlFeeText->setFont(font); + ui->labelCoinControlAfterFeeText->setFont(font); + ui->labelCoinControlChangeText->setFont(font); + ui->labelCoinControlChangeLabel->setFont(font); + ui->labelMinFeeWarning->setFont(font); + ui->fallbackFeeWarningLabel->setFont(font); + ui->checkBoxMinimumFee->setFont(font); + ui->checkBoxCoinControlChange->setFont(font); + ui->confirmationTargetLabel->setFont(font); + + + // Adjust font for all buttons + ui->sendButton->setFont(font); + ui->clearButton->setFont(font); + ui->addButton->setFont(font); + ui->pushButtonCoinControl->setFont(font); + ui->customFee->setFont(font); +} diff --git a/src/qt/sendcoinsdialog.h b/src/qt/sendcoinsdialog.h index 7656627a55..5abf2e3a07 100644 --- a/src/qt/sendcoinsdialog.h +++ b/src/qt/sendcoinsdialog.h @@ -67,6 +67,8 @@ public Q_SLOTS: bool fFeeMinimized; bool fAnonymousMode; const PlatformStyle *platformStyle; + void resizeEvent(QResizeEvent* event) override; + void adjustTextSize(int width, int height); // Process WalletModel::SendCoinsReturn and generate a pair consisting // of a message and message flags for use in Q_EMIT message(). @@ -125,6 +127,7 @@ private Q_SLOTS: QAbstractButton *yesButton; QTimer countDownTimer; int secDelay; + }; class SendGoPrivateDialog : public QMessageBox diff --git a/src/qt/sendcoinsentry.cpp b/src/qt/sendcoinsentry.cpp index 49fda59920..eb2d7e62dc 100644 --- a/src/qt/sendcoinsentry.cpp +++ b/src/qt/sendcoinsentry.cpp @@ -14,6 +14,7 @@ #include #include +#include SendCoinsEntry::SendCoinsEntry(const PlatformStyle *_platformStyle, QWidget *parent) : QStackedWidget(parent), @@ -265,3 +266,41 @@ bool SendCoinsEntry::updateLabel(const QString &address) ui->addAsLabel->setText(associatedLabel); return true; } +void SendCoinsEntry::resizeEvent(QResizeEvent* event) { + QStackedWidget::resizeEvent(event); + + const int newWidth = event->size().width(); + const int newHeight = event->size().height(); + + adjustTextSize(newWidth, newHeight); +} + + +void SendCoinsEntry::adjustTextSize(int width, int height) { + const double fontSizeScalingFactor = 130.0; + int baseFontSize = width / fontSizeScalingFactor; + int fontSize = std::max(12,baseFontSize); + QFont font = this->font(); + font.setPointSize(fontSize); + + ui->payToLabel->setFont(font); + ui->labellLabel->setFont(font); + ui->addAsLabel->setFont(font); + ui->amountLabel->setFont(font); + ui->messageLabel->setFont(font); + ui->messageTextLabel->setFont(font); + ui->payTo->setFont(font); + ui->payTo_is->setFont(font); + ui->memoLabel_is->setFont(font); + ui->memoTextLabel_is->setFont(font); + ui->amountLabel_is->setFont(font); + ui->payToLabel_s->setFont(font); + ui->payTo_s->setFont(font); + ui->memoLabel_s->setFont(font); + ui->memoTextLabel_s->setFont(font); + ui->amountLabel_s->setFont(font); + ui->checkboxSubtractFeeFromAmount->setFont(font); + ui->deleteButton->setFont(font); + ui->pasteButton->setFont(font); + ui->addressBookButton->setFont(font); +} \ No newline at end of file diff --git a/src/qt/sendcoinsentry.h b/src/qt/sendcoinsentry.h index 2c6bf35242..506981d5e3 100644 --- a/src/qt/sendcoinsentry.h +++ b/src/qt/sendcoinsentry.h @@ -73,6 +73,9 @@ private Q_SLOTS: bool isPcodeEntry; bool updateLabel(const QString &address); + void resizeEvent(QResizeEvent* event) override; + void adjustTextSize(int width, int height); + }; #endif // BITCOIN_QT_SENDCOINSENTRY_H diff --git a/src/qt/transactionview.cpp b/src/qt/transactionview.cpp index bbd3e4b049..7ad14a9ac5 100644 --- a/src/qt/transactionview.cpp +++ b/src/qt/transactionview.cpp @@ -67,7 +67,6 @@ TransactionView::TransactionView(const PlatformStyle *platformStyle, QWidget *pa headerLayout->addWidget(watchOnlyWidget); instantsendWidget = new QComboBox(this); - instantsendWidget->setFixedWidth(150); instantsendWidget->addItem(tr("All"), TransactionFilterProxy::InstantSendFilter_All); instantsendWidget->addItem(tr("Locked by InstantSend"), TransactionFilterProxy::InstantSendFilter_Yes); instantsendWidget->addItem(tr("Not locked by InstantSend"), TransactionFilterProxy::InstantSendFilter_No); @@ -711,3 +710,64 @@ void TransactionView::updateWatchOnlyColumn(bool fHaveWatchOnly) watchOnlyWidget->setVisible(fHaveWatchOnly); transactionView->setColumnHidden(TransactionTableModel::Watchonly, !fHaveWatchOnly); } + +// Handles resize events for the TransactionView widget by adjusting internal component sizes. +void TransactionView::resizeEvent(QResizeEvent* event) +{ + QWidget::resizeEvent(event); + + // Retrieve new dimensions from the resize event + const int newWidth = event->size().width(); + const int newHeight = event->size().height(); + + adjustTextSize(newWidth, newHeight); + + int headerHeight = newHeight * 0.1; + + // Calculate the height of widgets in the header subtracting a small margin + int widgetHeight = headerHeight - 5; + + // Determine widths for specific widgets as percentages of total width + int comboBoxesWidgetWidth = newWidth * 0.10; + int addressWidgetWidth = newWidth * 0.25; + + dateWidget->setFixedWidth(comboBoxesWidgetWidth); + typeWidget->setFixedWidth(comboBoxesWidgetWidth); + amountWidget->setFixedWidth(comboBoxesWidgetWidth); + instantsendWidget->setFixedWidth(comboBoxesWidgetWidth); + + int tableViewHeight = newHeight - headerHeight; + + // Calculate and set column widths based on new width, keeping proportions + int statusColumnWidth = newWidth * 0.05; + int watchOnlyColumnWidth = newWidth * 0.05; + int instantSendColumnWidth = newWidth * 0.05; + int dateColumnWidth = newWidth * 0.08; + int typeColumnWidth = newWidth * 0.10; + int addressColumnWidth = newWidth * 0.25; + + transactionView->setColumnWidth(TransactionTableModel::Status, statusColumnWidth); + transactionView->setColumnWidth(TransactionTableModel::Watchonly, watchOnlyColumnWidth); + transactionView->setColumnWidth(TransactionTableModel::InstantSend, instantSendColumnWidth); + transactionView->setColumnWidth(TransactionTableModel::Date, dateColumnWidth); + transactionView->setColumnWidth(TransactionTableModel::Type, typeColumnWidth); + transactionView->setColumnWidth(TransactionTableModel::ToAddress, addressColumnWidth); +} +void TransactionView::adjustTextSize(int width,int height){ + + const double fontSizeScalingFactor = 65.0; + int baseFontSize = std::min(width, height) / fontSizeScalingFactor; + int fontSize = std::min(15, std::max(12, baseFontSize)); + QFont font = this->font(); + font.setPointSize(fontSize); + + // Set font size for all labels + transactionView->setFont(font); + transactionView->horizontalHeader()->setFont(font); + transactionView->verticalHeader()->setFont(font); + dateWidget->setFont(font); + typeWidget->setFont(font); + amountWidget->setFont(font); + instantsendWidget->setFont(font); + addressWidget->setFont(font); +} \ No newline at end of file diff --git a/src/qt/transactionview.h b/src/qt/transactionview.h index fcebafc0ea..5b78cce3f7 100644 --- a/src/qt/transactionview.h +++ b/src/qt/transactionview.h @@ -9,6 +9,7 @@ #include #include +#include class PlatformStyle; class TransactionFilterProxy; @@ -37,6 +38,8 @@ class TransactionView : public QWidget explicit TransactionView(const PlatformStyle *platformStyle, QWidget *parent = 0); void setModel(WalletModel *model); + void resizeEvent(QResizeEvent* event) override; + void adjustTextSize(int width, int height); // Date ranges for filter enum DateEnum