Skip to content

Commit

Permalink
Handle segfaults on startup (#806)
Browse files Browse the repository at this point in the history
* GNOME: Throw runtime_error with reason if gresource failed to load

* GNOME: Print to stderr if failed to load blueprint files

* GNOME: mainwindow - Panic and exit early if m_window is null

This can happen for example when the complied ui files are missing, causing m_build and thereby m_window to be null

* libdenaro: Default to USD when locale isn't set

* GNOME: mainwindowcontroller - Show locale not set in debug info instead of crashing

* style changes

* Gnome: remove m_window == null check on startup

* Gnome: throw invalid argument exception if path for blueprint doesn't exist

* Gnome: about - remove unused variable

* Update libnick

* Use logging from libnick

* Throw runtime_error when blueprints are missing

* Update libnick

* Shared - Taskbar Logging

* mainwindowcontroller: add more logs

* mainwindowcontroller: code review fixes

* mainwindowcontroller: accout open and remove info logs

* All - Add Logs

---------

Co-authored-by: Nick Logozzo <nlogozzo225@gmail.com>
  • Loading branch information
JoseBritto and nlogozzo authored May 25, 2024
1 parent 692f09d commit 6c08d80
Show file tree
Hide file tree
Showing 44 changed files with 2,145 additions and 1,925 deletions.
2 changes: 1 addition & 1 deletion docs/po/denaro.pot
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2024-05-24 02:00-0400\n"
"POT-Creation-Date: 2024-05-24 21:54-0400\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
Expand Down
2 changes: 1 addition & 1 deletion flatpak/org.nickvision.money.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
{
"type": "git",
"url": "https://github.com/nickvisionapps/libnick",
"tag": "2024.3.1"
"tag": "2024.5.1"
}
]
},
Expand Down
6 changes: 2 additions & 4 deletions libdenaro/include/controllers/mainwindowcontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,16 +128,14 @@ namespace Nickvision::Money::Shared::Controllers
/**
* @brief Connects the main window to the taskbar interface.
* @param hwnd The main window handle
* @return True if connection successful, else false
*/
bool connectTaskbar(HWND hwnd);
void connectTaskbar(HWND hwnd);
#elif defined(__linux__)
/**
* @brief Connects the application to the taskbar interface.
* @param desktopFile The desktop file name (with the extension) of the running application
* @return True if connection successful, else false
*/
bool connectTaskbar(const std::string& desktopFile);
void connectTaskbar(const std::string& desktopFile);
#endif
/**
* @brief Gets whether or not an account file requires a password to open.
Expand Down
64 changes: 56 additions & 8 deletions libdenaro/src/controllers/mainwindowcontroller.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#include "controllers/mainwindowcontroller.h"
#include <ctime>
#include <format>
#include <locale>
#include <stdexcept>
#include <sstream>
#include <thread>
#include <libnick/app/aura.h>
Expand All @@ -25,7 +23,11 @@ namespace Nickvision::Money::Shared::Controllers
MainWindowController::MainWindowController()
: m_started{ false }
{
Aura::getActive().init("org.nickvision.money", "Nickvision Denaro", "Denaro");
#ifdef DEBUG
Aura::getActive().init("org.nickvision.money", "Nickvision Denaro", "Denaro", Logging::LogLevel::Debug);
#else
Aura::getActive().init("org.nickvision.money", "Nickvision Denaro", "Denaro", Logging::LogLevel::Info);
#endif
AppInfo& appInfo{ Aura::getActive().getAppInfo() };
appInfo.setVersion({ "2024.5.0-next" });
appInfo.setShortName(_("Denaro"));
Expand Down Expand Up @@ -117,7 +119,14 @@ namespace Nickvision::Money::Shared::Controllers
builder << StringHelpers::toString(name) << std::endl;
}
#elif defined(__linux__)
builder << std::locale("").name() << std::endl;
try
{
builder << std::locale("").name() << std::endl;
}
catch(...)
{
builder << "Locale not set" << std::endl;
}
#endif
//Gnuplot
builder << std::endl << Aura::getActive().sysExec("gnuplot --version");
Expand Down Expand Up @@ -197,22 +206,33 @@ namespace Nickvision::Money::Shared::Controllers
#endif
m_recentAccountsChanged.invoke({ Aura::getActive().getConfig<Configuration>("config").getRecentAccounts() });
m_started = true;
Aura::getActive().getLogger().log(Logging::LogLevel::Debug, "MainWindow started.");
}
}

void MainWindowController::checkForUpdates()
{
if(m_updater)
{
Aura::getActive().getLogger().log(Logging::LogLevel::Debug, "Checking for updates...");
std::thread worker{ [&]()
{
Version latest{ m_updater->fetchCurrentStableVersion() };
if (!latest.empty())
{
if (latest > Aura::getActive().getAppInfo().getVersion())
{
Aura::getActive().getLogger().log(Logging::LogLevel::Debug, "Update found: " + latest.toString());
m_notificationSent.invoke({ _("New update available"), NotificationSeverity::Success, "update" });
}
else
{
Aura::getActive().getLogger().log(Logging::LogLevel::Debug, "No updates found.");
}
}
else
{
Aura::getActive().getLogger().log(Logging::LogLevel::Warning, "Unable to fetch latest app version.");
}
} };
worker.detach();
Expand All @@ -224,26 +244,42 @@ namespace Nickvision::Money::Shared::Controllers
{
if(m_updater)
{
Aura::getActive().getLogger().log(Logging::LogLevel::Debug, "Fetching Windows app update...");
std::thread worker{ [&]()
{
bool res{ m_updater->windowsUpdate(VersionType::Stable) };
if (!res)
{
Aura::getActive().getLogger().log(Logging::LogLevel::Error, "Unbale to fetch Windows app update.");
m_notificationSent.invoke({ _("Unable to download and install update"), NotificationSeverity::Error, "error" });
}
} };
worker.detach();
}
}

bool MainWindowController::connectTaskbar(HWND hwnd)
void MainWindowController::connectTaskbar(HWND hwnd)
{
return m_taskbar.connect(hwnd);
if(m_taskbar.connect(hwnd))
{
Aura::getActive().getLogger().log(Logging::LogLevel::Debug, "Connected to Windows taskbar.");
}
else
{
Aura::getActive().getLogger().log(Logging::LogLevel::Error, "Unable to connect to Windows taskbar.");
}
}
#elif defined(__linux__)
bool MainWindowController::connectTaskbar(const std::string& desktopFile)
void MainWindowController::connectTaskbar(const std::string& desktopFile)
{
return m_taskbar.connect(desktopFile);
if(m_taskbar.connect(desktopFile))
{
Aura::getActive().getLogger().log(Logging::LogLevel::Debug, "Connected to Linux taskbar.");
}
else
{
Aura::getActive().getLogger().log(Logging::LogLevel::Error, "Unable to connect to Linux taskbar.");
}
}
#endif

Expand All @@ -269,15 +305,18 @@ namespace Nickvision::Money::Shared::Controllers
//Check if overwrite is allowed
if(!newAccountDialogController->getOverwriteExisting())
{
Aura::getActive().getLogger().log(Logging::LogLevel::Error, "Account exists and overwrite is disabled. (" + newAccountDialogController->getFilePath().string() + ")");
m_notificationSent.invoke({ _("This account already exists."), NotificationSeverity::Error });
return;
}
//Check if the account is open in the app (cannot delete if open)
if(m_accountViewControllers.contains(newAccountDialogController->getFilePath()))
{
Aura::getActive().getLogger().log(Logging::LogLevel::Error, "Cannot overwrite. Account is opened. (" + newAccountDialogController->getFilePath().string() + ")");
m_notificationSent.invoke({ _("This account cannot be overwritten."), NotificationSeverity::Error });
return;
}
Aura::getActive().getLogger().log(Logging::LogLevel::Warning, "Overwriting existing account file. (" + newAccountDialogController->getFilePath().string() + ")");
std::filesystem::remove(newAccountDialogController->getFilePath());
}
Configuration& config{ Aura::getActive().getConfig<Configuration>("config") };
Expand All @@ -296,15 +335,18 @@ namespace Nickvision::Money::Shared::Controllers
}
catch(const std::exception& e)
{
Aura::getActive().getLogger().log(Logging::LogLevel::Error, std::string(e.what()) + ". (" + newAccountDialogController->getFilePath().string() + ")");
m_notificationSent.invoke({ e.what(), NotificationSeverity::Error });
}
if(controller)
{
m_accountViewControllers[newAccountDialogController->getFilePath()] = controller;
config.addRecentAccount(controller->toRecentAccount());
config.save();
Aura::getActive().getLogger().log(Logging::LogLevel::Debug, "Config saved.");
m_recentAccountsChanged.invoke({ config.getRecentAccounts() });
m_accountAdded.invoke({ m_accountViewControllers[newAccountDialogController->getFilePath()] });
Aura::getActive().getLogger().log(Logging::LogLevel::Info, "Account created. (" + newAccountDialogController->getFilePath().string() + ")");
}
}

Expand All @@ -313,11 +355,13 @@ namespace Nickvision::Money::Shared::Controllers
//Check if the file is a Denaro account file
if(StringHelpers::toLower(path.extension().string()) != ".nmoney")
{
Aura::getActive().getLogger().log(Logging::LogLevel::Error, "Invalid file extension. (" + path.string() + ")");
m_notificationSent.invoke({ _("The file is not a Denaro account file."), NotificationSeverity::Error });
}
//Check if the account is already open
else if(m_accountViewControllers.contains(path))
{
Aura::getActive().getLogger().log(Logging::LogLevel::Warning, "Account already open. (" + path.string() + ")");
m_notificationSent.invoke({ _("The account is already open."), NotificationSeverity::Warning });
}
//Create the controller and open the account
Expand All @@ -330,6 +374,7 @@ namespace Nickvision::Money::Shared::Controllers
}
catch(const std::exception& e)
{
Aura::getActive().getLogger().log(Logging::LogLevel::Error, std::string(e.what()) + ". (" + path.string() + ")");
m_notificationSent.invoke({ e.what(), NotificationSeverity::Error });
}
if(controller)
Expand All @@ -338,8 +383,10 @@ namespace Nickvision::Money::Shared::Controllers
Configuration& config{ Aura::getActive().getConfig<Configuration>("config") };
config.addRecentAccount(controller->toRecentAccount());
config.save();
Aura::getActive().getLogger().log(Logging::LogLevel::Debug, "Config saved.");
m_recentAccountsChanged.invoke({ config.getRecentAccounts() });
m_accountAdded.invoke({ m_accountViewControllers[path] });
Aura::getActive().getLogger().log(Logging::LogLevel::Info, "Account opened. (" + path.string() + ")");
}
}
}
Expand All @@ -349,6 +396,7 @@ namespace Nickvision::Money::Shared::Controllers
Configuration& config{ Aura::getActive().getConfig<Configuration>("config") };
config.removeRecentAccount(account);
config.save();
Aura::getActive().getLogger().log(Logging::LogLevel::Debug, "Config saved.");
m_recentAccountsChanged.invoke({ config.getRecentAccounts() });
}
}
3 changes: 2 additions & 1 deletion libdenaro/src/controllers/preferencesviewcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,5 +75,6 @@ namespace Nickvision::Money::Shared::Controllers
void PreferencesViewController::saveConfiguration()
{
Aura::getActive().getConfig<Configuration>("config").save();
Aura::getActive().getLogger().log(Logging::LogLevel::Debug, "Config saved.");
}
}
}
27 changes: 20 additions & 7 deletions libdenaro/src/helpers/currencyhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <locale>
#include <memory>
#include <sstream>
#include <libnick/app/aura.h>
#include <libnick/helpers/stringhelpers.h>

using namespace Nickvision;
Expand Down Expand Up @@ -44,24 +45,36 @@ namespace Nickvision::Money::Shared
if(!systemCurrency)
{
systemCurrency = std::make_unique<Currency>();
systemCurrency->setSymbol(std::use_facet<std::moneypunct<char>>(std::locale("")).curr_symbol());
systemCurrency->setCode(std::use_facet<std::moneypunct<char, true>>(std::locale("")).curr_symbol());
systemCurrency->setDecimalSeparator(std::use_facet<std::moneypunct<char>>(std::locale("")).decimal_point());
systemCurrency->setGroupSeparator(std::use_facet<std::moneypunct<char>>(std::locale("")).thousands_sep());
std::locale locale;
try
{
locale = std::locale("");
}
catch (...)
{
App::Aura::getActive().getLogger().log(Logging::LogLevel::Warning, "Unknown system locale. Reverting to USD currency.");
systemCurrency->setCode("USD");
systemCurrency->setSymbol("$");
return *systemCurrency;
}
systemCurrency->setSymbol(std::use_facet<std::moneypunct<char>>(locale).curr_symbol());
systemCurrency->setCode(std::use_facet<std::moneypunct<char, true>>(locale).curr_symbol());
systemCurrency->setDecimalSeparator(std::use_facet<std::moneypunct<char>>(locale).decimal_point());
systemCurrency->setGroupSeparator(std::use_facet<std::moneypunct<char>>(locale).thousands_sep());
int numberIndex{ -1 };
int signIndex{ -1 };
int spaceIndex{ -1 };
for(int i = 0; i < 4; i++)
{
if(std::use_facet<std::moneypunct<char>>(std::locale("")).pos_format().field[i] == std::moneypunct<char>::value)
if(std::use_facet<std::moneypunct<char>>(locale).pos_format().field[i] == std::moneypunct<char>::value)
{
numberIndex = i;
}
if(std::use_facet<std::moneypunct<char>>(std::locale("")).pos_format().field[i] == std::moneypunct<char>::sign)
if(std::use_facet<std::moneypunct<char>>(locale).pos_format().field[i] == std::moneypunct<char>::sign)
{
signIndex = i;
}
if(std::use_facet<std::moneypunct<char>>(std::locale("")).pos_format().field[i] == std::moneypunct<char>::space)
if(std::use_facet<std::moneypunct<char>>(locale).pos_format().field[i] == std::moneypunct<char>::space)
{
spaceIndex = i;
}
Expand Down
11 changes: 11 additions & 0 deletions libdenaro/src/models/account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -632,9 +632,11 @@ namespace Nickvision::Money::Shared::Models
* CSV Header:
* ID;Date;Description;Type;RepeatInterval;RepeatFrom;RepeatEndDate;Amount;RGBA;UseGroupColor;Group;GroupName;GroupDescription;GroupRGBA
*/
Aura::getActive().getLogger().log(Logging::LogLevel::Info, "Starting CSV import... (" + m_path.string() + ")");
rapidcsv::Document csv{ path.string(), rapidcsv::LabelParams(0, -1), rapidcsv::SeparatorParams(';'), rapidcsv::ConverterParams(true), rapidcsv::LineReaderParams(true, '#', true) };
if(csv.GetColumnCount() != 14)
{
Aura::getActive().getLogger().log(Logging::LogLevel::Error, "CSV import failed. Invalid number of columns. (" + m_path.string() + ")");
return {};
}
ImportResult result;
Expand All @@ -643,6 +645,7 @@ namespace Nickvision::Money::Shared::Models
{
if(m_transactions.contains(csv.GetCell<int>(0, i))) //Transaction IDs must be unique
{
Aura::getActive().getLogger().log(Logging::LogLevel::Warning, "Skipping row " + std::to_string(i) + ". ID already exists. (" + m_path.string() + ")");
continue;
}
Transaction t{ csv.GetCell<int>(0, i) };
Expand Down Expand Up @@ -688,11 +691,15 @@ namespace Nickvision::Money::Shared::Models
}
}
m_repository.commitTransaction();
Aura::getActive().getLogger().log(Logging::LogLevel::Info, "Imported " + std::to_string(result.getNewTransactionIds().size()) + " transaction(s) from CSV. (" + m_path.string() + ")");
Aura::getActive().getLogger().log(Logging::LogLevel::Info, "Imported " + std::to_string(result.getNewGroupIds().size()) + " groups(s) from CSV. (" + m_path.string() + ")");
Aura::getActive().getLogger().log(Logging::LogLevel::Info, "Imported " + std::to_string(result.getNewTags().size()) + " tags(s) from CSV. (" + m_path.string() + ")");
return result;
}

ImportResult Account::importFromOFX(const std::filesystem::path& path, const Color& defaultTransactionColor)
{
Aura::getActive().getLogger().log(Logging::LogLevel::Info, "Starting OFX import... (" + m_path.string() + ")");
ImportResult result;
//Read all lines from ofx file
std::ifstream file{ path };
Expand Down Expand Up @@ -773,11 +780,13 @@ namespace Nickvision::Money::Shared::Models
}
m_repository.commitTransaction();
}
Aura::getActive().getLogger().log(Logging::LogLevel::Info, "Imported " + std::to_string(result.getNewTransactionIds().size()) + " transaction(s) from OFX. (" + m_path.string() + ")");
return result;
}

ImportResult Account::importFromQIF(const std::filesystem::path& path, const Color& defaultTransactionColor, const Color& defaultGroupColor)
{
Aura::getActive().getLogger().log(Logging::LogLevel::Info, "Starting QIF import... (" + m_path.string() + ")");
ImportResult result;
//Parse qif file
std::ifstream file{ path };
Expand Down Expand Up @@ -882,6 +891,8 @@ namespace Nickvision::Money::Shared::Models
}
m_repository.commitTransaction();
}
Aura::getActive().getLogger().log(Logging::LogLevel::Info, "Imported " + std::to_string(result.getNewTransactionIds().size()) + " transaction(s) from QIF. (" + m_path.string() + ")");
Aura::getActive().getLogger().log(Logging::LogLevel::Info, "Imported " + std::to_string(result.getNewGroupIds().size()) + " groups(s) from QIF. (" + m_path.string() + ")");
return result;
}

Expand Down
4 changes: 2 additions & 2 deletions libdenaro/src/models/accountmetadata.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ namespace Nickvision::Money::Shared::Models
{
return m_showTagsList;
}

void AccountMetadata::setShowTagsList(bool showTagsList)
{
m_showTagsList = showTagsList;
Expand All @@ -115,4 +115,4 @@ namespace Nickvision::Money::Shared::Models
{
m_sortFirstToLast = sortFirstToLast;
}
}
}
Loading

0 comments on commit 6c08d80

Please sign in to comment.