summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAldrik Ramaekers <aldrikboy@gmail.com>2025-10-26 17:23:28 +0100
committerAldrik Ramaekers <aldrikboy@gmail.com>2025-10-26 17:23:28 +0100
commit60488d722bf29f3ff0ce3e08b90f30523a8d7b6d (patch)
treec2e01243d8a0d970c35e250b66a66a226ab230dc /src
parent5e06ad208e32330b662af90ce41613f5421095cb (diff)
loading animations and block navigation while writing to disk
Diffstat (limited to 'src')
-rw-r--r--src/administration.cpp23
-rw-r--r--src/administration_writer.cpp174
-rw-r--r--src/ui/helpers.cpp100
-rw-r--r--src/ui/imgui_extensions.cpp95
-rw-r--r--src/ui/ui_contacts.cpp25
-rw-r--r--src/ui/ui_expenses.cpp36
-rw-r--r--src/ui/ui_invoices.cpp34
-rw-r--r--src/ui/ui_main.cpp1
-rw-r--r--src/ui/ui_projects.cpp23
-rw-r--r--src/ui/ui_settings.cpp85
10 files changed, 362 insertions, 234 deletions
diff --git a/src/administration.cpp b/src/administration.cpp
index 9fdfe7e..cb158e2 100644
--- a/src/administration.cpp
+++ b/src/administration.cpp
@@ -26,7 +26,7 @@
static ledger g_administration;
-static data_changed_event data_changed_event_callback = 0;
+static data_changed_event administration_data_changed_event_callback = 0;
static data_deleted_event data_deleted_event_callback = 0;
static invoice_changed_event invoice_changed_event_callback = 0;
static contact_changed_event contact_changed_event_callback = 0;
@@ -58,7 +58,6 @@ static void create_default_cost_centers()
list_append(&g_administration.cost_centers, tb);\
g_administration.next_id++;\
if (costcenter_changed_event_callback) costcenter_changed_event_callback(tb);\
- if (data_changed_event_callback) data_changed_event_callback();\
}
ADD_COSTCENTER("costcenter.general_expenses", "GENE");
@@ -81,9 +80,9 @@ static s32 create_sequence_number()
// Callback functions.
// =======================
-void administration::set_data_changed_event_callback(data_changed_event ev)
+void administration::set_administration_data_changed_event_callback(data_changed_event ev)
{
- data_changed_event_callback = ev;
+ administration_data_changed_event_callback = ev;
}
void administration::set_data_deleted_event_callback(data_deleted_event ev)
@@ -227,7 +226,7 @@ ai_service administration::get_ai_service()
void administration::set_ai_service(ai_service provider)
{
g_administration.ai_service = provider;
- if (data_changed_event_callback) data_changed_event_callback();
+ if (administration_data_changed_event_callback) administration_data_changed_event_callback();
}
void administration::set_next_id(s32 nr)
@@ -650,7 +649,6 @@ void administration::company_info_set(contact data)
strops::copy(g_administration.default_currency, get_default_currency_for_country(g_administration.company_info.address.country_code), MAX_LEN_CURRENCY);
if (contact_changed_event_callback) contact_changed_event_callback(&data);
- if (data_changed_event_callback) data_changed_event_callback();
}
// Contact functions.
@@ -690,7 +688,6 @@ a_err administration::contact_add(contact data)
g_administration.next_id++;
if (contact_changed_event_callback) contact_changed_event_callback(new_contact);
- if (data_changed_event_callback) data_changed_event_callback();
return A_ERR_SUCCESS;
}
@@ -708,7 +705,6 @@ a_err administration::contact_update(contact data)
memops::copy(c, &data, sizeof(data));
if (contact_changed_event_callback) contact_changed_event_callback(c);
- if (data_changed_event_callback) data_changed_event_callback();
list_iterator_stop(&g_administration.contacts);
return A_ERR_SUCCESS;
@@ -1001,7 +997,6 @@ a_err administration::project_add(project data)
g_administration.next_id++;
if (project_changed_event_callback) project_changed_event_callback(new_project);
- if (data_changed_event_callback) data_changed_event_callback();
return A_ERR_SUCCESS;
}
@@ -1020,7 +1015,6 @@ a_err administration::project_update(project data)
list_iterator_stop(&g_administration.projects);
if (project_changed_event_callback) project_changed_event_callback(c);
- if (data_changed_event_callback) data_changed_event_callback();
return A_ERR_SUCCESS;
}
@@ -1163,7 +1157,6 @@ a_err administration::tax_rate_enable(tax_rate data)
g_administration.next_id++;
if (taxrate_changed_event_callback) taxrate_changed_event_callback(&data);
- if (data_changed_event_callback) data_changed_event_callback();
return A_ERR_SUCCESS;
}
@@ -1291,7 +1284,6 @@ a_err administration::cost_center_add(cost_center data)
g_administration.next_id++;
if (costcenter_changed_event_callback) costcenter_changed_event_callback(tb);
- if (data_changed_event_callback) data_changed_event_callback();
return A_ERR_SUCCESS;
}
@@ -1310,7 +1302,6 @@ a_err administration::cost_center_update(cost_center data)
list_iterator_stop(&g_administration.cost_centers);
if (costcenter_changed_event_callback) costcenter_changed_event_callback(c);
- if (data_changed_event_callback) data_changed_event_callback();
return A_ERR_SUCCESS;
}
@@ -1502,7 +1493,6 @@ a_err administration::invoice_update(invoice* inv)
list_iterator_stop(&g_administration.invoices);
if (invoice_changed_event_callback) invoice_changed_event_callback(c);
- if (data_changed_event_callback) data_changed_event_callback();
return A_ERR_SUCCESS;
}
@@ -1568,7 +1558,6 @@ a_err administration::invoice_add(invoice* inv)
else g_administration.expense_count++;
if (invoice_changed_event_callback) invoice_changed_event_callback(new_inv);
- if (data_changed_event_callback) data_changed_event_callback();
return A_ERR_SUCCESS;
}
@@ -1784,10 +1773,6 @@ static void administration_recalculate_billing_item_totals(billing_item* item)
{
item->tax = item->net * (rate.rate/100.0f);
}
- else
- {
- assert(0);
- }
item->total = item->net + item->tax;
}
diff --git a/src/administration_writer.cpp b/src/administration_writer.cpp
index 77b1445..c45ec6e 100644
--- a/src/administration_writer.cpp
+++ b/src/administration_writer.cpp
@@ -18,6 +18,7 @@
#include <xml.h>
#include <threads.h>
+#include "config.hpp"
#include "memops.hpp"
#include "logger.hpp"
#include "ui.hpp"
@@ -28,51 +29,164 @@
#include "tinyfiledialogs.h"
#include "file_templates.hpp"
-mtx_t _save_file_mutex;
+static mtx_t _save_file_mutex;
+static bool _is_writing = false;
+static write_completed_event _write_completed_ev = 0;
+
+bool administration_writer::is_writing()
+{
+ return _is_writing;
+}
+
+void administration_writer::set_write_completed_event_callback(write_completed_event ev)
+{
+ _write_completed_ev = ev;
+}
static void on_administration_data_changed()
{
- if (administration_writer::save_all_administration_info_blocking()) {
- ui::set_status(locale::get("status.saved"));
- }
- else {
- ui::set_status(locale::get("status.saveFailed"));
- }
+ _is_writing = true;
+
+ auto* func = new auto([]() {
+ administration_writer::save_administration_info_blocking();
+
+ _is_writing = false;
+ if (_write_completed_ev) _write_completed_ev();
+ });
+
+ auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(); delete f; return 0; };
+ thrd_t thr; thrd_create(&thr, trampoline, 0);
}
static void on_administration_data_deleted(char id[MAX_LEN_ID])
{
- administration_writer::delete_entry(id);
+ _is_writing = true;
+
+ char* id_copy = (char*)memops::alloc(MAX_LEN_ID);
+ strops::copy(id_copy, id, MAX_LEN_ID);
+
+ auto* func = new auto([](void* arg) {
+ char* id = (char*)arg;
+ administration_writer::delete_entry(id);
+ administration_writer::save_administration_info_blocking();
+ memops::unalloc(arg);
+
+ _is_writing = false;
+ if (_write_completed_ev) _write_completed_ev();
+ });
+
+ auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(arg); delete f; return 0; };
+ thrd_t thr; thrd_create(&thr, trampoline, (void*)id_copy);
}
-static void on_invoice_changed(invoice* invoice)
+static void on_invoice_changed(invoice* inv)
{
- administration_writer::save_invoice_blocking(*invoice);
+ _is_writing = true;
+
+ invoice inv_copy = administration::invoice_create_copy(inv);
+ invoice* inv_copy2 = (invoice*)memops::alloc(sizeof(invoice));
+ memops::copy(inv_copy2, &inv_copy, sizeof(invoice));
+
+ auto* func = new auto([](void* arg) {
+ invoice* inv = (invoice*)arg;
+ administration_writer::save_invoice_blocking(*inv);
+ administration_writer::save_administration_info_blocking();
+ administration::invoice_destroy(inv);
+
+ _is_writing = false;
+ if (_write_completed_ev) _write_completed_ev();
+ });
+
+ auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(arg); delete f; return 0; };
+ thrd_t thr; thrd_create(&thr, trampoline, (void*)inv_copy2);
}
-static void on_contact_changed_changed(contact* contact)
+static void on_contact_changed_changed(contact* cc)
{
- administration_writer::save_contact_blocking(*contact);
+ _is_writing = true;
+
+ contact* cc_copy = (contact*)memops::alloc(sizeof(contact));
+ memops::copy(cc_copy, cc, sizeof(contact));
+
+ auto* func = new auto([](void* arg) {
+ contact* cc = (contact*)arg;
+ administration_writer::save_contact_blocking(*cc);
+ administration_writer::save_administration_info_blocking();
+ memops::unalloc(arg);
+
+ _is_writing = false;
+ if (_write_completed_ev) _write_completed_ev();
+ });
+
+ auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(arg); delete f; return 0; };
+ thrd_t thr; thrd_create(&thr, trampoline, (void*)cc_copy);
}
static void on_taxrate_changed_changed(tax_rate* rate)
{
- administration_writer::save_tax_rate_blocking(*rate);
+ _is_writing = true;
+
+ tax_rate* rate_copy = (tax_rate*)memops::alloc(sizeof(tax_rate));
+ memops::copy(rate_copy, rate, sizeof(tax_rate));
+
+ auto* func = new auto([](void* arg) {
+ tax_rate* rate = (tax_rate*)arg;
+ administration_writer::save_tax_rate_blocking(*rate);
+ administration_writer::save_administration_info_blocking();
+ memops::unalloc(arg);
+
+ _is_writing = false;
+ if (_write_completed_ev) _write_completed_ev();
+ });
+
+ auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(arg); delete f; return 0; };
+ thrd_t thr; thrd_create(&thr, trampoline, (void*)rate_copy);
}
-static void on_costcenter_changed_changed(cost_center* cost_center)
+static void on_costcenter_changed_changed(cost_center* cc)
{
- administration_writer::save_cost_center_blocking(*cost_center);
+ _is_writing = true;
+
+ cost_center* cc_copy = (cost_center*)memops::alloc(sizeof(cost_center));
+ memops::copy(cc_copy, cc, sizeof(cost_center));
+
+ auto* func = new auto([](void* arg) {
+ cost_center* cc = (cost_center*)arg;
+ administration_writer::save_cost_center_blocking(*cc);
+ memops::unalloc(arg);
+
+ _is_writing = false;
+ if (_write_completed_ev) _write_completed_ev();
+ });
+
+ auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(arg); delete f; return 0; };
+ thrd_t thr; thrd_create(&thr, trampoline, (void*)cc_copy);
}
-static void on_project_changed_changed(project* project)
+static void on_project_changed_changed(project* pp)
{
- administration_writer::save_project_blocking(*project);
+ _is_writing = true;
+
+ project* pp_copy = (project*)memops::alloc(sizeof(project));
+ memops::copy(pp_copy, pp, sizeof(project));
+
+ auto* func = new auto([](void* arg) {
+ project* pp = (project*)arg;
+ administration_writer::save_project_blocking(*pp);
+ administration_writer::save_administration_info_blocking();
+ memops::unalloc(arg);
+
+ _is_writing = false;
+ if (_write_completed_ev) _write_completed_ev();
+ });
+
+ auto trampoline = [](void* arg) -> int { auto* f = static_cast<decltype(func)>(arg); (*f)(arg); delete f; return 0; };
+ thrd_t thr; thrd_create(&thr, trampoline, (void*)pp_copy);
}
bool administration_writer::create()
{
- administration::set_data_changed_event_callback(on_administration_data_changed);
+ administration::set_administration_data_changed_event_callback(on_administration_data_changed);
administration::set_data_deleted_event_callback(on_administration_data_deleted);
administration::set_invoice_changed_event_callback(on_invoice_changed);
administration::set_contact_changed_event_callback(on_contact_changed_changed);
@@ -80,7 +194,7 @@ bool administration_writer::create()
administration::set_costcenter_changed_event_callback(on_costcenter_changed_changed);
administration::set_project_changed_event_callback(on_project_changed_changed);
- return mtx_init(&_save_file_mutex, mtx_plain) == thrd_success;
+ return mtx_init(&_save_file_mutex, mtx_plain|mtx_recursive) == thrd_success;
}
void administration_writer::destroy()
@@ -101,17 +215,23 @@ static char* copy_template(const char* template_str, int* buf_size)
static bool zip_entry_exists(char* entry)
{
+ mtx_lock(&_save_file_mutex);
+
struct zip_t *zip_read = zip_open(administration::get_file_path(), 0, 'r');
int result = zip_entry_open(zip_read, entry);
zip_entry_close(zip_read);
zip_close(zip_read);
+ mtx_unlock(&_save_file_mutex);
+
return result == 0;
}
static bool delete_entry_by_name(char* entry)
{
STOPWATCH_START;
+
+ mtx_lock(&_save_file_mutex);
bool result = 1;
struct zip_t *zip_write = zip_open(administration::get_file_path(), 0, 'a');
@@ -124,6 +244,8 @@ static bool delete_entry_by_name(char* entry)
if (result) logger::info("Deleted entry '%s' in %.3fms.", entry, STOPWATCH_TIME);
else logger::error("Failed to delete entry '%s'.", entry);
+ mtx_unlock(&_save_file_mutex);
+
return result;
}
@@ -137,6 +259,8 @@ bool administration_writer::delete_entry(char* id)
static bool write_to_zip(char* entry_to_replace, char* orig_content, int final_length)
{
+ mtx_lock(&_save_file_mutex);
+
bool result = 1;
bool entry_exists = zip_entry_exists(entry_to_replace);
if (entry_exists) delete_entry_by_name(entry_to_replace);
@@ -149,6 +273,16 @@ static bool write_to_zip(char* entry_to_replace, char* orig_content, int final_l
zip_entry_close(zip_write);
zip_close(zip_write);
+
+ #if WRITE_DELAY_SEC != 0
+ struct timespec time;
+ time.tv_sec = WRITE_DELAY_SEC;
+ time.tv_nsec = 0;
+ thrd_sleep(&time, NULL);
+ #endif
+
+ mtx_unlock(&_save_file_mutex);
+
return result;
}
@@ -705,7 +839,7 @@ bool administration_writer::save_contact_blocking(contact c)
/////////////////////////////
//// Administration info
/////////////////////////////
-bool administration_writer::save_all_administration_info_blocking()
+bool administration_writer::save_administration_info_blocking()
{
STOPWATCH_START;
diff --git a/src/ui/helpers.cpp b/src/ui/helpers.cpp
deleted file mode 100644
index 476e780..0000000
--- a/src/ui/helpers.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-* Copyright (c) 2025 Aldrik Ramaekers <aldrik.ramaekers@gmail.com>
-*
-* Permission to use, copy, modify, and/or distribute this software for any
-* purpose with or without fee is hereby granted, provided that the above
-* copyright notice and this permission notice appear in all copies.
-*
-* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-*/
-
-#include "ui.hpp"
-#include "imgui.h"
-#include "strops.hpp"
-
-#define STATUS_DURATION 4.0f
-#define STATUS_FLASH_INTERVAL 0.1f
-#define STATUS_MAX_FLASHES 2
-
-namespace ui {
-
- ImFont* fontBold;
- ImFont* fontBig;
-
- static status current_status;
-
- void ui::draw_status()
- {
- float region_width = ImGui::GetContentRegionAvail().x;
- float text_width = ImGui::CalcTextSize(current_status.text).x;
-
- if (current_status.loading)
- {
- ImGui::SetCursorPosX(ImGui::GetCursorPosX() + region_width - text_width - 20.0f);
- ImGui::Text("%c", "|/-\\"[(int)(ImGui::GetTime() / 0.1f) & 3]);
- return;
- }
-
- if (current_status.visible)
- {
- ImGui::SetCursorPosX(ImGui::GetCursorPosX() + region_width - text_width);
- ImGui::PushStyleColor(ImGuiCol_Text, current_status.color);
- ImGui::TextUnformatted(current_status.text);
- ImGui::PopStyleColor();
- }
-
- ImGuiIO& io = ImGui::GetIO();
- current_status.time += io.DeltaTime;
-
- if (current_status.time >= STATUS_FLASH_INTERVAL && current_status.flash_count < STATUS_MAX_FLASHES)
- {
- current_status.visible = !current_status.visible;
- if (current_status.visible) current_status.flash_count++;
- current_status.time = 0.0f;
- }
-
- if (current_status.time >= STATUS_DURATION)
- {
- current_status.text[0] = 0;
- }
- }
-
- static void set_status_ex(const char* txt, int color)
- {
- current_status.flash_count = 0;
- current_status.visible = true;
- current_status.time = 0.0f;
- current_status.color = color;
- current_status.loading = false;
- strops::copy(current_status.text, txt, STATUS_TEXT_LEN);
- }
-
- void ui::set_status_error(const char* txt)
- {
- set_status_ex(txt, config::colors::COLOR_ERROR);
- }
-
- void ui::set_status(const char* txt)
- {
- set_status_ex(txt, config::colors::COLOR_DEFAULT);
- }
-
- void ui::set_status_loading(bool loading)
- {
- current_status.visible = true;
- current_status.time = 0.0f;
- current_status.loading = loading;
- }
-
- status ui::get_status()
- {
- return current_status;
- }
-
-} \ No newline at end of file
diff --git a/src/ui/imgui_extensions.cpp b/src/ui/imgui_extensions.cpp
index d1abc58..359fc17 100644
--- a/src/ui/imgui_extensions.cpp
+++ b/src/ui/imgui_extensions.cpp
@@ -4,11 +4,104 @@
#include "config.hpp"
#include "locales.hpp"
#include "countries.hpp"
-#include "administration.hpp"
#include "tinyfiledialogs.h"
+#include "administration.hpp"
+#include "administration_writer.hpp"
+
+namespace ui {
+ ImFont* fontBold;
+ ImFont* fontBig;
+}
namespace ImGui
{
+ bool CheckboxX(const char* label, bool* v, bool disabled, bool show_loading_indicator_while_disabled)
+ {
+ bool result = false;
+ if (disabled) ImGui::BeginDisabled();
+ if (!disabled || !show_loading_indicator_while_disabled)
+ {
+ result = ImGui::Checkbox(label, v);
+ }
+ else
+ {
+ bool tmp = false;
+ result = ImGui::Checkbox(label, &tmp);
+ if (result) *v = !(*v);
+
+ float radius = 10.0f;
+ ImVec2 p_min = ImGui::GetItemRectMin();
+ ImVec2 p_max = ImGui::GetItemRectMax();
+ ImVec2 center = ImVec2((p_min.x + p_max.x) * 0.5f - radius, (p_min.y + p_max.y) * 0.5f - radius);
+
+ ImGui::SetCursorScreenPos(ImVec2(center.x, center.y));
+
+ const ImVec4 col = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
+ const ImVec4 bg = ImGui::GetStyleColorVec4(ImGuiCol_Button);
+ ImGui::LoadingIndicatorCircle("##loadingAnim", radius, bg, col, 6, 4.0f);
+ }
+
+ if (disabled) ImGui::EndDisabled();
+ return result;
+ }
+
+ static ImVec2 CalcButtonSize(const char* label)
+ {
+ ImGuiStyle& style = ImGui::GetStyle();
+ ImVec2 text_size = ImGui::CalcTextSize(label, nullptr, true);
+ ImVec2 button_size = ImVec2(
+ text_size.x + style.FramePadding.x * 2.0f,
+ text_size.y + style.FramePadding.y * 2.0f
+ );
+ return button_size;
+ }
+
+ bool Button(const char* label, bool block_while_writing_to_disk, bool show_loading_indicator_while_blocked)
+ {
+ if (block_while_writing_to_disk)
+ {
+ if (administration_writer::is_writing())
+ {
+ if (show_loading_indicator_while_blocked) {
+ ImGui::PushID(label);
+ ImGui::BeginDisabled();
+ bool result = ImGui::Button("", CalcButtonSize(label));
+
+ float radius = 10.0f;
+ ImVec2 p_min = ImGui::GetItemRectMin();
+ ImVec2 p_max = ImGui::GetItemRectMax();
+ ImVec2 center = ImVec2((p_min.x + p_max.x) * 0.5f - radius, (p_min.y + p_max.y) * 0.5f - radius);
+
+ ImGui::SetCursorScreenPos(ImVec2(center.x, center.y));
+
+ const ImVec4 col = ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered);
+ const ImVec4 bg = ImGui::GetStyleColorVec4(ImGuiCol_Button);
+ ImGui::LoadingIndicatorCircle("##loadingAnim", radius, bg, col, 6, 4.0f);
+
+ ImGui::EndDisabled();
+ ImGui::PopID();
+
+ return result;
+ }
+ else
+ {
+ ImGui::BeginDisabled();
+ bool result = ImGui::Button(label);
+ ImGui::EndDisabled();
+ return result;
+ }
+ }
+ else
+ {
+ return ImGui::Button(label);
+ }
+ }
+ else
+ {
+ return ImGui::Button(label);
+ }
+ }
+
void InputTextWithError(const char* text, char* buffer, size_t buf_size, bool has_error)
{
if (has_error) {
diff --git a/src/ui/ui_contacts.cpp b/src/ui/ui_contacts.cpp
index 0f1716f..5d92f8a 100644
--- a/src/ui/ui_contacts.cpp
+++ b/src/ui/ui_contacts.cpp
@@ -154,10 +154,15 @@ static void draw_contact_list()
}
}
+static void _reset_to_default_view()
+{
+ current_view_state = ui::view_state::LIST_ALL;
+}
+
static void draw_contacts_create()
{
- if (ImGui::Button(locale::get("form.back"))) {
- current_view_state = ui::view_state::LIST_ALL;
+ if (ImGui::Button(locale::get("form.back"), true, false)) {
+ _reset_to_default_view();
}
ImGui::ContactForm(&active_contact, false, false);
@@ -167,17 +172,17 @@ static void draw_contacts_create()
if (!can_save) ImGui::BeginDisabled();
// Save button
ImGui::Spacing();
- if (ImGui::Button(locale::get("form.save"))) {
+ if (ImGui::Button(locale::get("form.save"), true)) {
+ administration_writer::set_write_completed_event_callback(_reset_to_default_view);
administration::contact_add(active_contact);
- current_view_state = ui::view_state::LIST_ALL;
}
if (!can_save) ImGui::EndDisabled();
}
static void draw_contacts_update()
{
- if (ImGui::Button(locale::get("form.back"))) {
- current_view_state = ui::view_state::LIST_ALL;
+ if (ImGui::Button(locale::get("form.back"), true, false)) {
+ _reset_to_default_view();
}
ImGui::ContactForm(&active_contact, false, false);
@@ -187,9 +192,9 @@ static void draw_contacts_update()
if (!can_save) ImGui::BeginDisabled();
// Save button
ImGui::Spacing();
- if (ImGui::Button(locale::get("form.save"))) {
+ if (ImGui::Button(locale::get("form.save"), true)) {
+ administration_writer::set_write_completed_event_callback(_reset_to_default_view);
administration::contact_update(active_contact);
- current_view_state = ui::view_state::LIST_ALL;
}
if (!can_save) ImGui::EndDisabled();
}
@@ -203,8 +208,8 @@ void ui::draw_contacts()
case ui::view_state::EDIT_EXISTING: draw_contacts_update(); break;
case ui::view_state::VIEW_EXISTING:
- if (ImGui::Button(locale::get("form.back"))) {
- current_view_state = ui::view_state::LIST_ALL;
+ if (ImGui::Button(locale::get("form.back"), true, false)) {
+ _reset_to_default_view();
}
ImGui::ContactForm(&active_contact, true, false);
diff --git a/src/ui/ui_expenses.cpp b/src/ui/ui_expenses.cpp
index d1121b1..8635273 100644
--- a/src/ui/ui_expenses.cpp
+++ b/src/ui/ui_expenses.cpp
@@ -294,11 +294,17 @@ static void draw_expenses_list()
}
}
+static void _reset_to_default_view()
+{
+ current_view_state = ui::view_state::LIST_ALL;
+ ui::destroy_expenses();
+ ui::setup_expenses();
+}
static void draw_expense_update()
{
- if (ImGui::Button(locale::get("form.back"))) {
- current_view_state = ui::view_state::LIST_ALL;
+ if (ImGui::Button(locale::get("form.back"), true, false)) {
+ _reset_to_default_view();
}
draw_expense_form(&active_invoice);
@@ -307,13 +313,9 @@ static void draw_expense_update()
if (!can_save) ImGui::BeginDisabled();
ImGui::Spacing();
- if (ImGui::Button(locale::get("form.save"))) {
+ if (ImGui::Button(locale::get("form.save"), true)) {
+ administration_writer::set_write_completed_event_callback(_reset_to_default_view);
administration::invoice_update(&active_invoice);
-
- current_view_state = ui::view_state::LIST_ALL;
-
- ui::destroy_expenses();
- ui::setup_expenses();
}
if (!can_save) ImGui::EndDisabled();
@@ -321,8 +323,8 @@ static void draw_expense_update()
static void draw_expense_create()
{
- if (ImGui::Button(locale::get("form.back"))) {
- current_view_state = ui::view_state::LIST_ALL;
+ if (ImGui::Button(locale::get("form.back"), true, false)) {
+ _reset_to_default_view();
}
draw_expense_form(&active_invoice);
@@ -331,13 +333,9 @@ static void draw_expense_create()
if (!can_save) ImGui::BeginDisabled();
ImGui::Spacing();
- if (ImGui::Button(locale::get("form.save"))) {
+ if (ImGui::Button(locale::get("form.save"), true)) {
+ administration_writer::set_write_completed_event_callback(_reset_to_default_view);
administration::invoice_add(&active_invoice);
-
- current_view_state = ui::view_state::LIST_ALL;
-
- ui::destroy_expenses();
- ui::setup_expenses();
}
if (!can_save) ImGui::EndDisabled();
@@ -345,8 +343,8 @@ static void draw_expense_create()
static void draw_expense_view()
{
- if (ImGui::Button(locale::get("form.back"))) {
- current_view_state = ui::view_state::LIST_ALL;
+ if (ImGui::Button(locale::get("form.back"), true, false)) {
+ _reset_to_default_view();
}
draw_expense_form(&active_invoice, true);
@@ -365,7 +363,7 @@ static void draw_import_request()
}
else {
if (ImGui::Button(locale::get("form.back"))) {
- current_view_state = ui::view_state::LIST_ALL;
+ _reset_to_default_view();
active_import_request = 0;
return;
}
diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp
index 8741965..3987b72 100644
--- a/src/ui/ui_invoices.cpp
+++ b/src/ui/ui_invoices.cpp
@@ -388,11 +388,17 @@ static void draw_invoices_list()
}
}
+static void _reset_to_default_view()
+{
+ current_view_state = ui::view_state::LIST_ALL;
+ ui::destroy_invoices();
+ ui::setup_invoices();
+}
static void draw_invoice_update()
{
- if (ImGui::Button(locale::get("form.back"))) {
- current_view_state = ui::view_state::LIST_ALL;
+ if (ImGui::Button(locale::get("form.back"), true, false)) {
+ _reset_to_default_view();
}
draw_invoice_form(&active_invoice);
@@ -401,13 +407,9 @@ static void draw_invoice_update()
if (!can_save) ImGui::BeginDisabled();
ImGui::Spacing();
- if (ImGui::Button(locale::get("form.save"))) {
+ if (ImGui::Button(locale::get("form.save"), true)) {
+ administration_writer::set_write_completed_event_callback(_reset_to_default_view);
administration::invoice_update(&active_invoice);
-
- current_view_state = ui::view_state::LIST_ALL;
-
- ui::destroy_invoices();
- ui::setup_invoices();
}
if (!can_save) ImGui::EndDisabled();
@@ -415,8 +417,8 @@ static void draw_invoice_update()
static void draw_invoice_create()
{
- if (ImGui::Button(locale::get("form.back"))) {
- current_view_state = ui::view_state::LIST_ALL;
+ if (ImGui::Button(locale::get("form.back"), true, false)) {
+ _reset_to_default_view();
}
draw_invoice_form(&active_invoice);
@@ -425,13 +427,9 @@ static void draw_invoice_create()
if (!can_save) ImGui::BeginDisabled();
ImGui::Spacing();
- if (ImGui::Button(locale::get("form.save"))) {
+ if (ImGui::Button(locale::get("form.save"), true)) {
+ administration_writer::set_write_completed_event_callback(_reset_to_default_view);
administration::invoice_add(&active_invoice);
-
- current_view_state = ui::view_state::LIST_ALL;
-
- ui::destroy_invoices();
- ui::setup_invoices();
}
if (!can_save) ImGui::EndDisabled();
@@ -439,8 +437,8 @@ static void draw_invoice_create()
static void draw_invoice_view()
{
- if (ImGui::Button(locale::get("form.back"))) {
- current_view_state = ui::view_state::LIST_ALL;
+ if (ImGui::Button(locale::get("form.back"), true, false)) {
+ _reset_to_default_view();
}
draw_invoice_form(&active_invoice, true);
diff --git a/src/ui/ui_main.cpp b/src/ui/ui_main.cpp
index 48b1364..d4b9c58 100644
--- a/src/ui/ui_main.cpp
+++ b/src/ui/ui_main.cpp
@@ -160,7 +160,6 @@ void ui::draw_main()
}
ImGui::SameLine();
- ui::draw_status();
ImGui::End();
ImGui::PopStyleVar();
diff --git a/src/ui/ui_projects.cpp b/src/ui/ui_projects.cpp
index 82597b4..94f2be6 100644
--- a/src/ui/ui_projects.cpp
+++ b/src/ui/ui_projects.cpp
@@ -26,22 +26,24 @@ static project selected_for_cancellation;
static project active_project;
-void ui::setup_projects()
+static void _reset_to_default_view()
{
current_view_state = ui::view_state::LIST_ALL;
active_project = administration::project_create_empty();
}
+void ui::setup_projects()
+{
+ _reset_to_default_view();
+}
+
static void draw_project_form()
{
float widthAvailable = ImGui::GetContentRegionAvail().x;
bool viewing_only = (current_view_state == ui::view_state::VIEW_EXISTING);
- static const char* selected_country = NULL;
- if (ImGui::Button(locale::get("form.back"))) {
- current_view_state = ui::view_state::LIST_ALL;
- active_project = administration::project_create_empty();
- selected_country = 0;
+ if (ImGui::Button(locale::get("form.back"), true, false)) {
+ _reset_to_default_view();
return;
}
ImGui::Spacing();
@@ -63,7 +65,10 @@ static void draw_project_form()
if (!can_save) ImGui::BeginDisabled();
// Save button
ImGui::Spacing();
- if (ImGui::Button(locale::get("form.save"))) {
+ if (ImGui::Button(locale::get("form.save"), true)) {
+
+ administration_writer::set_write_completed_event_callback(_reset_to_default_view);
+
if (current_view_state == ui::view_state::CREATE) {
administration::project_add(active_project);
}
@@ -71,10 +76,6 @@ static void draw_project_form()
else if (current_view_state == ui::view_state::EDIT_EXISTING) {
administration::project_update(active_project);
}
-
- current_view_state = ui::view_state::LIST_ALL;
- selected_country = 0;
- active_project = administration::project_create_empty();
}
if (!can_save) ImGui::EndDisabled();
}
diff --git a/src/ui/ui_settings.cpp b/src/ui/ui_settings.cpp
index e15bde0..1c8f92b 100644
--- a/src/ui/ui_settings.cpp
+++ b/src/ui/ui_settings.cpp
@@ -58,6 +58,13 @@ void ui::setup_settings()
}
}
+static bool is_writing_vat_rate = false;
+static u32 writing_vat_rate_index = 0;
+static void _vat_rate_write_complete_callback()
+{
+ is_writing_vat_rate = false;
+}
+
static void draw_vat_rates()
{
tax_rate_type type_iter = tax_rate_type::TAX_RATE_OUTGOING_INVOICE;
@@ -84,7 +91,10 @@ static void draw_vat_rates()
ImGui::TableSetColumnIndex(0);
bool toggle = administration::tax_rate_is_enabled(c) == A_ERR_SUCCESS;
- if (ImGui::Checkbox("##toggle", &toggle)) {
+ if (ImGui::CheckboxX("##toggle", &toggle, is_writing_vat_rate, i == writing_vat_rate_index)) {
+ writing_vat_rate_index = i;
+ is_writing_vat_rate = true;
+ administration_writer::set_write_completed_event_callback(_vat_rate_write_complete_callback);
if (toggle) administration::tax_rate_enable(c);
else administration::tax_rate_disable(c);
}
@@ -113,12 +123,26 @@ static void draw_vat_rates()
if (type_iter < TAX_RATE_TYPE_END) goto go_again;
}
-static void draw_cost_centers()
+static bool is_adding_cost_center = false;
+static bool is_editing_cost_center = false;
+static cost_center new_cost_center;
+
+static void _cost_center_update_callback()
{
- static bool is_adding_item = false;
- static cost_center new_cost_center;
+ is_editing_cost_center = false;
+ is_adding_cost_center = false;
+
+ administration::cost_center_update(new_cost_center);
+
+ memops::zero(&new_cost_center, sizeof(new_cost_center));
+
+ ui::destroy_settings();
+ ui::setup_settings();
+ select_company_tab = 0;
+}
- static bool is_editing_item = false;
+static void draw_cost_centers()
+{
static u32 editing_item_index = 0;
if (ImGui::BeginTable("TableCostCenters", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
@@ -137,7 +161,7 @@ static void draw_cost_centers()
// Column 2: When editing, show inputs for new description. Else show stored description and check for modify request.
ImGui::TableSetColumnIndex(1);
- if (is_editing_item && editing_item_index == i)
+ if (is_editing_cost_center && editing_item_index == i)
{
bool is_desc_valid = !(administration::cost_center_is_valid(new_cost_center) & A_ERR_MISSING_DESCRIPTION);
if (!is_desc_valid) ImGui::PushStyleColor(ImGuiCol_FrameBg, IM_COL32(105, 43, 43, 255));
@@ -146,23 +170,16 @@ static void draw_cost_centers()
if (!is_desc_valid) ImGui::BeginDisabled();
ImGui::SameLine();
- if (ImGui::Button(locale::get("form.save"))) {
- is_editing_item = false;
- is_adding_item = false;
-
+ if (ImGui::Button(locale::get("form.save"), true)) {
+ administration_writer::set_write_completed_event_callback(_cost_center_update_callback);
administration::cost_center_update(new_cost_center);
-
- memops::zero(&new_cost_center, sizeof(new_cost_center));
-
- ui::destroy_settings();
- ui::setup_settings();
}
if (!is_desc_valid) ImGui::EndDisabled();
ImGui::SameLine();
- if (ImGui::Button(locale::get("form.cancel"))) {
- is_editing_item = false;
- is_adding_item = false;
+ if (ImGui::Button(locale::get("form.cancel"), true, false)) {
+ is_editing_cost_center = false;
+ is_adding_cost_center = false;
memops::zero(&new_cost_center, sizeof(new_cost_center));
}
}
@@ -172,8 +189,8 @@ static void draw_cost_centers()
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
{
- is_editing_item = true;
- is_adding_item = false;
+ is_editing_cost_center = true;
+ is_adding_cost_center = false;
editing_item_index = i;
new_cost_center = c;
}
@@ -182,7 +199,7 @@ static void draw_cost_centers()
// When adding a new item. Show inputs for code and description, check validity, and handle save/cancel.
// Form for new entry is displayed at bottom of list.
- if (is_adding_item)
+ if (is_adding_cost_center)
{
ImGui::TableNextRow();
@@ -201,21 +218,17 @@ static void draw_cost_centers()
if (!can_save) ImGui::BeginDisabled();
ImGui::SameLine();
- if (ImGui::Button(locale::get("form.create")))
+ if (ImGui::Button(locale::get("form.create"), true))
{
- is_adding_item = false;
- is_editing_item = false;
+ administration_writer::set_write_completed_event_callback(_cost_center_update_callback);
administration::cost_center_add(new_cost_center);
-
- ui::destroy_settings();
- ui::setup_settings();
}
if (!can_save) ImGui::EndDisabled();
ImGui::SameLine();
- if (ImGui::Button(locale::get("form.cancel"))) {
- is_adding_item = false;
- is_editing_item = false;
+ if (ImGui::Button(locale::get("form.cancel"), true)) {
+ is_adding_cost_center = false;
+ is_editing_cost_center = false;
memops::zero(&new_cost_center, sizeof(new_cost_center));
}
}
@@ -224,11 +237,11 @@ static void draw_cost_centers()
}
// If not adding a new item already, show create button at bottom of list.
- if (!is_adding_item && ImGui::Button(locale::get("form.create")))
+ if (!is_adding_cost_center && ImGui::Button(locale::get("form.create")))
{
new_cost_center = administration::cost_center_create_empty();
- is_adding_item = true;
- is_editing_item = false;
+ is_adding_cost_center = true;
+ is_editing_cost_center = false;
}
}
@@ -317,7 +330,8 @@ static void draw_services()
ImGui::EndDisabled();
}
- if (ImGui::Button(locale::get("form.save"))) {
+ if (ImGui::Button(locale::get("form.save"), true)) {
+ administration_writer::set_write_completed_event_callback(0);
administration::set_ai_service(new_service);
}
}
@@ -336,7 +350,8 @@ void ui::draw_settings()
bool can_save = administration::contact_is_valid(company_info) == A_ERR_SUCCESS;
if (!can_save) ImGui::BeginDisabled();
ImGui::Spacing();
- if (ImGui::Button(locale::get("form.save"))) {
+ if (ImGui::Button(locale::get("form.save"), true)) {
+ administration_writer::set_write_completed_event_callback(0);
administration::company_info_set(company_info);
}
if (!can_save) ImGui::EndDisabled();