summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO2
-rw-r--r--include/administration_reader.hpp1
-rw-r--r--include/countries.hpp2
-rw-r--r--include/ui.hpp2
-rw-r--r--src/administration_reader.cpp14
-rw-r--r--src/administration_writer.cpp111
-rw-r--r--src/countries.cpp8
-rw-r--r--src/countries/nl.cpp1
-rw-r--r--src/ui/imgui_extensions.cpp66
-rw-r--r--src/ui/ui_contacts.cpp8
-rw-r--r--src/ui/ui_expenses.cpp7
-rw-r--r--src/ui/ui_invoices.cpp5
-rw-r--r--src/ui/ui_main.cpp1
-rw-r--r--src/ui/ui_settings.cpp4
14 files changed, 82 insertions, 150 deletions
diff --git a/TODO b/TODO
index 95fb219..87e86e4 100644
--- a/TODO
+++ b/TODO
@@ -9,7 +9,7 @@ Testing:
Improvements:
- "price includes tax" toggle that recalculates billing item tax, net and total
-- Loading animation on save button while file is being saved. navigation should be disabled untill file is saved.
+- Loading animation on save button while file is being saved. navigation should be disabled untill file is saved
Features:
- Handle invalid api key response from AI backends and display in settings UI
diff --git a/include/administration_reader.hpp b/include/administration_reader.hpp
index f8f8766..b2311af 100644
--- a/include/administration_reader.hpp
+++ b/include/administration_reader.hpp
@@ -20,7 +20,6 @@ namespace administration_reader {
bool open_new();
bool open_existing(char* file_path);
- bool save_new();
bool import_administration_info(char* buffer, size_t buffer_size);
bool import_tax_rate(char* buffer, size_t buffer_size);
diff --git a/include/countries.hpp b/include/countries.hpp
index 0e3704f..5364eff 100644
--- a/include/countries.hpp
+++ b/include/countries.hpp
@@ -22,6 +22,7 @@ typedef struct
{
char* country_code;
bool is_EU;
+ bool enabled; // true = can be used as operating country.
time_t (*get_default_invoice_expire_duration)();
@@ -41,6 +42,7 @@ namespace country {
time_t get_default_invoice_expire_duration(char* country_code);
bool is_EU(char* country_code);
+ bool is_enabled(char* country_code);
bool tax_is_implemented(char* country_code);
void fill_tax_report_with_categories(char* country_code, tax_report* report);
bool add_billing_item_to_tax_report(char* country_code, tax_report* report, invoice* inv, billing_item* item);
diff --git a/include/ui.hpp b/include/ui.hpp
index 92cb8f5..68b1aa4 100644
--- a/include/ui.hpp
+++ b/include/ui.hpp
@@ -106,7 +106,7 @@ namespace ImGui
bool FormInvoiceFileSelector(char* text, char* buffer);
void FormContactAutocomplete(contact* buffer, bool has_error);
void FormInputTextWithErrorHint(const char* hint, char* buffer, size_t buf_size, bool has_error);
- void FormCountryCombo(char* buffer, size_t buf_size);
+ void FormCountryCombo(char* buffer, size_t buf_size, bool activated_only = false);
void FormContactTypeCombo(contact_type* type);
void FormCostCenterCombo(char* costcenter_id);
void FormProjectCombo(char* project_id);
diff --git a/src/administration_reader.cpp b/src/administration_reader.cpp
index 80d0eac..321a622 100644
--- a/src/administration_reader.cpp
+++ b/src/administration_reader.cpp
@@ -38,20 +38,6 @@ bool administration_reader::open_new()
return true;
}
-bool administration_reader::save_new()
-{
- // @locale::get
- char const * lFilterPatterns[1] = { "*.openbook" };
- char* save_path = tinyfd_saveFileDialog("Select destination", NULL, 1, lFilterPatterns, NULL);
-
- if (!save_path) return false;
-
- administration::set_file_path(save_path);
- administration_writer::save_all_async();
-
- return true;
-}
-
bool administration_reader::open_existing(char* file_path)
{
if (file_path == NULL) {
diff --git a/src/administration_writer.cpp b/src/administration_writer.cpp
index 04068e7..77b1445 100644
--- a/src/administration_writer.cpp
+++ b/src/administration_writer.cpp
@@ -531,23 +531,6 @@ bool administration_writer::save_invoice_blocking(invoice inv)
return result;
}
-static bool save_all_invoices_blocking()
-{
- bool result = 1;
- u32 num_invoices = administration::invoice_count();
- u32 buffer_size = sizeof(invoice) * num_invoices;
- invoice* invoice_buffer = (invoice*)memops::alloc(buffer_size);
- num_invoices = administration::invoice_get_all(invoice_buffer);
-
- for (u32 i = 0; i < num_invoices; i++) {
- invoice c = invoice_buffer[i];
- if (!administration_writer::save_invoice_blocking(c)) result = 0;
- }
-
- memops::unalloc(invoice_buffer);
- return result;
-}
-
/////////////////////////////
//// Projects
/////////////////////////////
@@ -590,23 +573,6 @@ bool administration_writer::save_project_blocking(project project)
return result;
}
-static bool save_all_projects_blocking()
-{
- bool result = 1;
- u32 num_projects = administration::project_count();
- u32 buffer_size = sizeof(project) * num_projects;
- project* project_buffer = (project*)memops::alloc(buffer_size);
- num_projects = administration::project_get_all(project_buffer);
-
- for (u32 i = 0; i < num_projects; i++) {
- project c = project_buffer[i];
- if (!administration_writer::save_project_blocking(c)) result = 0;
- }
-
- memops::unalloc(project_buffer);
- return result;
-}
-
/////////////////////////////
//// Cost centers
/////////////////////////////
@@ -695,28 +661,6 @@ bool administration_writer::save_tax_rate_blocking(tax_rate rate)
return result;
}
-bool administration_writer::save_all_tax_rates_blocking()
-{
- /*
- //// Get all data.
- u32 num_rates = administration::tax_rate_count();
- u32 buffer_size = sizeof(tax_rate) * num_rates;
- tax_rate* rate_buffer = (tax_rate*)memops::alloc(buffer_size);
- num_rates = administration::tax_rate_get_all(rate_buffer);
-
- bool result = 1;
-
- for (u32 i = 0; i < num_rates; i++) {
- tax_rate c = rate_buffer[i];
- if (!administration_writer::save_tax_rate_blocking(c)) result = 0;
- }
-
- memops::unalloc(rate_buffer);
- return result;
- */
- return 1;
-}
-
/////////////////////////////
//// Contacts
/////////////////////////////
@@ -758,29 +702,6 @@ bool administration_writer::save_contact_blocking(contact c)
return result;
}
-static bool save_all_contacts_blocking()
-{
- //// Get all data.
- u32 num_contacts = administration::contact_count();
- u32 buffer_size = sizeof(contact) * num_contacts;
- contact* contact_buffer = (contact*)memops::alloc(buffer_size);
- num_contacts = administration::contact_get_all(contact_buffer);
-
- bool result = 1;
-
- // Save company info.
- if (!administration_writer::save_contact_blocking(administration::company_info_get())) result = 0;
-
- // Save contacts.
- for (u32 i = 0; i < num_contacts; i++) {
- contact c = ((contact*)contact_buffer)[i];
- if (!administration_writer::save_contact_blocking(c)) result = 0;
- }
-
- memops::unalloc(contact_buffer);
- return result;
-}
-
/////////////////////////////
//// Administration info
/////////////////////////////
@@ -812,36 +733,4 @@ bool administration_writer::save_all_administration_info_blocking()
else logger::error("Failed to save administration info.");
return result;
-}
-
-/////////////////////////////
-//// Other
-/////////////////////////////
-static int write_all_t(void *arg) {
- (void)arg;
- int result = 1;
-
- mtx_lock(&_save_file_mutex);
-
- if (!save_all_invoices_blocking()) result = 0;
- if (!save_all_projects_blocking()) result = 0;
- if (!administration_writer::save_all_administration_info_blocking()) result = 0;
- if (!administration_writer::save_all_tax_rates_blocking()) result = 0;
- if (!administration_writer::save_all_cost_centers_blocking()) result = 0;
- if (!save_all_contacts_blocking()) result = 0;
-
- mtx_unlock(&_save_file_mutex);
-
- return result;
-}
-
-bool administration_writer::save_all_async()
-{
- write_all_t(0);
- //thrd_t thr;
- //if (thrd_create(&thr, write_all_t, 0) != thrd_success) {
- // return false;
- //}
-
- return true;
} \ No newline at end of file
diff --git a/src/countries.cpp b/src/countries.cpp
index 4456284..337b10b 100644
--- a/src/countries.cpp
+++ b/src/countries.cpp
@@ -250,6 +250,14 @@ bool country::is_EU(char* country_code)
return country_map[index].is_EU;
}
+bool country::is_enabled(char* country_code)
+{
+ s32 index = get_index_by_country_code(country_code);
+ if (index == -1) return 0;
+
+ return country_map[index].enabled;
+}
+
time_t country::get_default_invoice_expire_duration(char* country_code)
{
s32 index = get_index_by_country_code(country_code);
diff --git a/src/countries/nl.cpp b/src/countries/nl.cpp
index fb19a8f..c4abc9d 100644
--- a/src/countries/nl.cpp
+++ b/src/countries/nl.cpp
@@ -542,6 +542,7 @@ u32 _nl_get_available_tax_rates(tax_rate* buffer, u32 buffer_size)
country_impl _nl_country_impl = {
"NL",
true,
+ true,
_nl_get_default_invoice_expire_duration,
_nl_fill_tax_report_with_categories,
_nl_add_billing_item_to_tax_report,
diff --git a/src/ui/imgui_extensions.cpp b/src/ui/imgui_extensions.cpp
index b3b20f8..494cfc8 100644
--- a/src/ui/imgui_extensions.cpp
+++ b/src/ui/imgui_extensions.cpp
@@ -82,18 +82,28 @@ namespace ImGui
return result;
}
- void FormCountryCombo(char* buffer, size_t buf_size)
+ void FormCountryCombo(char* buffer, size_t buf_size, bool activated_only)
{
const char* selected_country = 0;
float widthAvailable = ImGui::GetContentRegionAvail().x;
ImGui::SetNextItemWidth(widthAvailable*0.5f);
+ u32 country_cursor = 0;
const char* countries[300];
+ bool enabled_countries[300] = {1};
+
for (int x = 0; x < country::get_count(); x++)
{
char locale_str[20];
strops::format(locale_str, 20, "country.%s", country::get_code_by_index(x));
countries[x] = locale::get(locale_str);
+
+ if (activated_only) {
+ enabled_countries[x] = country::is_enabled(country::get_code_by_index(x));
+ }
+ else {
+ enabled_countries[x] = 1;
+ }
}
for (int i = 0; i < country::get_count(); i++)
@@ -116,10 +126,12 @@ namespace ImGui
{
for (int n = 0; n < country::get_count(); n++)
{
- bool is_selected = (selected_country == countries[n]);
- if (ImGui::Selectable(countries[n], is_selected)) {
- selected_country = countries[n];
- selected_country_index = n;
+ if (enabled_countries[n]) {
+ bool is_selected = (selected_country == countries[n]);
+ if (ImGui::Selectable(countries[n], is_selected)) {
+ selected_country = countries[n];
+ selected_country_index = n;
+ }
}
}
ImGui::EndCombo();
@@ -151,11 +163,42 @@ namespace ImGui
}
}
+ typedef struct
+ {
+ const char* id;
+ bool is_open;
+ } open_autocomplete_ref;
+
int TextInputWithAutocomplete(const char* hint, char* buffer, size_t buf_size, char* suggestions[], int suggestion_count, bool has_error)
{
int result = -1;
- static bool is_open = false;
+
+ const u32 max_ref_count = 10;
+ static open_autocomplete_ref open_refs[max_ref_count] = {0};
+ open_autocomplete_ref* found_ref = 0;
+ {
+ for (u32 i = 0; i < max_ref_count; i++) {
+ if (open_refs[i].id == buffer) {
+ found_ref = &open_refs[i];
+ break;
+ }
+ }
+
+ if (!found_ref) {
+ for (u32 i = 0; i < max_ref_count; i++) {
+ if (open_refs[i].id == 0) {
+ found_ref = &open_refs[i];
+ found_ref->id = buffer;
+ found_ref->is_open = false;
+ break;
+ }
+ }
+ }
+ if (!found_ref) assert(0);
+ }
+
+ bool is_open = found_ref->is_open;
if (has_error) {
ImGui::PushStyleColor(ImGuiCol_Border, config::colors::COLOR_ERROR_OUTLINE);
@@ -172,8 +215,10 @@ namespace ImGui
}
- if (buffer[0] == '\0' && is_open) is_open = false;
- if (suggestion_count == 0 && is_open) is_open = false;
+ if (buffer[0] == '\0' && is_open)
+ is_open = false;
+ if (suggestion_count == 0 && is_open)
+ is_open = false;
bool is_active = ImGui::IsItemActive();
if (is_active && buffer[0] != '\0' && suggestion_count > 0)
@@ -192,7 +237,8 @@ namespace ImGui
(mouse_pos.x < win_pos.x || mouse_pos.x > win_pos.x + win_size.x ||
mouse_pos.y < win_pos.y || mouse_pos.y > win_pos.y + win_size.y);
- if (mouse_clicked_outside) is_open = false;
+ if (mouse_clicked_outside)
+ is_open = false;
for (int i = 0; i < suggestion_count; ++i)
{
@@ -211,6 +257,8 @@ namespace ImGui
ImGui::EndChild();
}
}
+
+ found_ref->is_open = is_open;
return result;
}
diff --git a/src/ui/ui_contacts.cpp b/src/ui/ui_contacts.cpp
index ff1f424..4e15bb1 100644
--- a/src/ui/ui_contacts.cpp
+++ b/src/ui/ui_contacts.cpp
@@ -28,7 +28,7 @@ static contact selected_for_removal;
static contact active_contact;
-void draw_address_form(address* buffer, a_err last_err)
+void draw_address_form(address* buffer, a_err last_err, bool active_countries_only = false)
{
ImGui::FormInputTextWithErrorHint(locale::get("contact.form.address1"), buffer->address1, IM_ARRAYSIZE(buffer->address1), last_err & A_ERR_MISSING_ADDRESS1);
ImGui::FormInputTextWithErrorHint(locale::get("contact.form.address2"), buffer->address2, IM_ARRAYSIZE(buffer->address2), 0);
@@ -36,7 +36,7 @@ void draw_address_form(address* buffer, a_err last_err)
ImGui::FormInputTextWithErrorHint(locale::get("contact.form.postal"), buffer->postal, IM_ARRAYSIZE(buffer->postal), last_err & A_ERR_MISSING_POSTAL);
ImGui::FormInputTextWithErrorHint(locale::get("contact.form.region"), buffer->region, IM_ARRAYSIZE(buffer->region), 0);
- ImGui::FormCountryCombo(buffer->country_code, IM_ARRAYSIZE(buffer->country_code));
+ ImGui::FormCountryCombo(buffer->country_code, IM_ARRAYSIZE(buffer->country_code), active_countries_only);
}
void ui::setup_contacts()
@@ -65,7 +65,7 @@ void draw_addressee_form_ex(delivery_info* buffer, bool viewing_only = false)
ImGui::PopID();
}
-void draw_contact_form_ex(contact* buffer, bool viewing_only = false, bool with_autocomplete = false)
+void draw_contact_form_ex(contact* buffer, bool viewing_only = false, bool with_autocomplete = false, bool active_countries_only = false)
{
a_err last_err = administration::contact_is_valid(*buffer);
@@ -79,7 +79,7 @@ void draw_contact_form_ex(contact* buffer, bool viewing_only = false, bool with_
if (with_autocomplete) ImGui::FormContactAutocomplete(buffer, last_err & A_ERR_MISSING_NAME);
else ImGui::FormInputTextWithErrorHint(locale::get("contact.form.fullname"), buffer->name, IM_ARRAYSIZE(buffer->name), last_err & A_ERR_MISSING_NAME);
- draw_address_form(&buffer->address, last_err);
+ draw_address_form(&buffer->address, last_err, active_countries_only);
ImGui::FormContactTypeCombo(&buffer->type);
diff --git a/src/ui/ui_expenses.cpp b/src/ui/ui_expenses.cpp
index 6a4eebd..e09db5b 100644
--- a/src/ui/ui_expenses.cpp
+++ b/src/ui/ui_expenses.cpp
@@ -35,12 +35,11 @@ static invoice selected_for_removal = {0};
static billing_item* invoice_items_buffer = 0;
void draw_addressee_form_ex(delivery_info* buffer, bool viewing_only = false);
-void draw_contact_form_ex(contact* buffer, bool viewing_only = false, bool with_autocomplete = false);
+void draw_contact_form_ex(contact* buffer, bool viewing_only, bool with_autocomplete, bool active_countries_only);
void draw_invoice_items_form(invoice* invoice, bool outgoing = true);
void ui::destroy_expenses()
{
- administration::invoice_destroy(&active_invoice);
memops::unalloc(invoice_items_buffer);
}
@@ -99,12 +98,12 @@ static void draw_expense_form(invoice* buffer, bool viewing_only = false)
ImGui::Separator();
ImGui::Text(locale::get("invoice.form.billinginformation"));
- draw_contact_form_ex(&buffer->customer, false, true);
+ draw_contact_form_ex(&buffer->customer, false, true, false);
ImGui::Separator();
ImGui::Text(locale::get("invoice.form.supplier"));
- draw_contact_form_ex(&buffer->supplier, false, true);
+ draw_contact_form_ex(&buffer->supplier, false, true, false);
ImGui::Checkbox(locale::get("invoice.form.triangulation"), &buffer->is_triangulation);
if (buffer->is_triangulation) {
diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp
index d932bfd..4ae325f 100644
--- a/src/ui/ui_invoices.cpp
+++ b/src/ui/ui_invoices.cpp
@@ -32,12 +32,11 @@ static invoice selected_for_removal = {0};
static billing_item* invoice_items_buffer = 0;
-void draw_contact_form_ex(contact* buffer, bool viewing_only = false, bool with_autocomplete = false);
+void draw_contact_form_ex(contact* buffer, bool viewing_only, bool with_autocomplete, bool active_countries_only);
void draw_addressee_form_ex(delivery_info* buffer, bool viewing_only = false);
void ui::destroy_invoices()
{
- administration::invoice_destroy(&active_invoice);
memops::unalloc(invoice_items_buffer);
}
@@ -211,7 +210,7 @@ static void draw_invoice_form(invoice* buffer, bool viewing_only = false)
ImGui::Separator();
ImGui::Text(locale::get("invoice.form.billinginformation"));
- draw_contact_form_ex(&buffer->customer, false, true);
+ draw_contact_form_ex(&buffer->customer, false, true, false);
ImGui::Checkbox(locale::get("invoice.form.triangulation"), &buffer->is_triangulation);
if (buffer->is_triangulation) {
diff --git a/src/ui/ui_main.cpp b/src/ui/ui_main.cpp
index 84dab1b..48b1364 100644
--- a/src/ui/ui_main.cpp
+++ b/src/ui/ui_main.cpp
@@ -74,7 +74,6 @@ void ui::draw_main()
{
if (ImGui::MenuItem("New")) { administration_reader::open_new(); }
if (ImGui::MenuItem("Open")) { administration_reader::open_existing(NULL); }
- if (ImGui::MenuItem("Save")) { administration_reader::save_new(); }
ImGui::EndMenu();
}
diff --git a/src/ui/ui_settings.cpp b/src/ui/ui_settings.cpp
index 2a310d3..06409b7 100644
--- a/src/ui/ui_settings.cpp
+++ b/src/ui/ui_settings.cpp
@@ -325,6 +325,8 @@ static void draw_services()
}
}
+void draw_contact_form_ex(contact* buffer, bool viewing_only, bool with_autocomplete, bool active_countries_only);
+
void ui::draw_settings()
{
if (ImGui::BeginTabBar("SettingsTabBar"))
@@ -332,7 +334,7 @@ void ui::draw_settings()
if (ImGui::BeginTabItem(locale::get("settings.table.company"), nullptr, select_company_tab == 1 ? ImGuiTabItemFlags_SetSelected : 0))
{
select_company_tab = 0;
- draw_contact_form(&company_info);
+ draw_contact_form_ex(&company_info, false, false, true);
// Save button.
bool can_save = administration::contact_is_valid(company_info) == A_ERR_SUCCESS;