LCOV - code coverage report
Current view: top level - libgnucash/engine - gnc-option-impl.cpp (source / functions) Coverage Total Hit
Test: gnucash.info Lines: 57.5 % 553 318
Test Date: 2025-02-07 16:25:45 Functions: 41.7 % 139 58
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /********************************************************************\
       2                 :             :  * gnc-option-impl.cpp -- Application options system                     *
       3                 :             :  * Copyright (C) 2019 John Ralls <jralls@ceridwen.us>               *
       4                 :             :  *                                                                  *
       5                 :             :  * This program is free software; you can redistribute it and/or    *
       6                 :             :  * modify it under the terms of the GNU General Public License as   *
       7                 :             :  * published by the Free Software Foundation; either version 2 of   *
       8                 :             :  * the License, or (at your option) any later version.              *
       9                 :             :  *                                                                  *
      10                 :             :  * This program is distributed in the hope that it will be useful,  *
      11                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
      12                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
      13                 :             :  * GNU General Public License for more details.                     *
      14                 :             :  *                                                                  *
      15                 :             :  * You should have received a copy of the GNU General Public License*
      16                 :             :  * along with this program; if not, contact:                        *
      17                 :             :  *                                                                  *
      18                 :             :  * Free Software Foundation           Voice:  +1-617-542-5942       *
      19                 :             :  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
      20                 :             :  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
      21                 :             :  *                                                                  *
      22                 :             : \********************************************************************/
      23                 :             : 
      24                 :             : #include "gnc-option-impl.hpp"
      25                 :             : #include "gnc-datetime.hpp"
      26                 :             : #include "gnc-option-uitype.hpp"
      27                 :             : #include "guid.hpp"
      28                 :             : #include <cassert>
      29                 :             : #include <sstream>
      30                 :             : #include <numeric>
      31                 :             : 
      32                 :             : #include "gnc-accounting-period.h"
      33                 :             : #include "gnc-session.h"
      34                 :             : #include "gncOwner.h"
      35                 :             : 
      36                 :             : static const QofLogModule log_module{"gnc.options"};
      37                 :             : 
      38                 :             : const std::string GncOptionMultichoiceValue::c_empty_string{""};
      39                 :             : const std::string GncOptionMultichoiceValue::c_list_string{"multiple values"};
      40                 :             : 
      41                 :             : static inline GncOwnerType
      42                 :           0 : ui_type_to_owner_type(GncOptionUIType ui_type)
      43                 :             : {
      44                 :           0 :     if (ui_type == GncOptionUIType::CUSTOMER)
      45                 :           0 :         return GNC_OWNER_CUSTOMER;
      46                 :           0 :     if (ui_type == GncOptionUIType::VENDOR)
      47                 :           0 :         return GNC_OWNER_VENDOR;
      48                 :           0 :     if (ui_type == GncOptionUIType::EMPLOYEE)
      49                 :           0 :         return GNC_OWNER_EMPLOYEE;
      50                 :           0 :     if (ui_type == GncOptionUIType::JOB)
      51                 :           0 :         return GNC_OWNER_JOB;
      52                 :           0 :     return GNC_OWNER_NONE;
      53                 :             : }
      54                 :             : 
      55                 :             : static GncOwner*
      56                 :          93 : make_owner_ptr(const GncOwner* owner)
      57                 :             : {
      58                 :          93 :     if (!owner)
      59                 :          84 :         return nullptr;
      60                 :           9 :     auto rv{gncOwnerNew()};
      61                 :           9 :     gncOwnerCopy(owner, rv);
      62                 :           9 :     return rv;
      63                 :             : }
      64                 :             : 
      65                 :          21 : GncOptionGncOwnerValue::GncOptionGncOwnerValue(
      66                 :             :     const char* section, const char* name,
      67                 :             :     const char* key, const char* doc_string,
      68                 :          21 :     const GncOwner* value, GncOptionUIType ui_type) :
      69                 :             :     OptionClassifier{section, name, key, doc_string},
      70                 :          21 :     m_ui_type(ui_type), m_value{make_owner_ptr(value)},
      71                 :         126 :     m_default_value{make_owner_ptr(value)} {}
      72                 :             : 
      73                 :          21 : GncOptionGncOwnerValue::GncOptionGncOwnerValue(const GncOptionGncOwnerValue& from) :
      74                 :          63 :     OptionClassifier{from.m_section, from.m_name, from.m_sort_tag,
      75                 :          21 :                      from.m_doc_string},
      76                 :          21 :     m_ui_type(from.get_ui_type()), m_value{make_owner_ptr(from.get_value())},
      77                 :          42 :     m_default_value{make_owner_ptr(from.get_default_value())} {}
      78                 :             : 
      79                 :             : void
      80                 :           9 : GncOptionGncOwnerValue::set_value(const GncOwner* new_value)
      81                 :             : {
      82                 :           9 :     m_value.reset(make_owner_ptr(new_value));
      83                 :           9 :     m_dirty = true;
      84                 :           9 : }
      85                 :             : 
      86                 :             : void
      87                 :           0 : GncOptionGncOwnerValue::set_default_value(const GncOwner *new_value)
      88                 :             : {
      89                 :           0 :     m_value.reset(make_owner_ptr(new_value));
      90                 :           0 :     m_default_value.reset(make_owner_ptr(new_value));
      91                 :           0 : }
      92                 :             : 
      93                 :             : const GncOwner*
      94                 :          58 : GncOptionGncOwnerValue::get_value() const
      95                 :             : {
      96                 :          58 :     return m_value.get();
      97                 :             : }
      98                 :             : 
      99                 :             : const GncOwner*
     100                 :          23 : GncOptionGncOwnerValue::get_default_value() const
     101                 :             : {
     102                 :          23 :     return m_default_value.get();
     103                 :             : }
     104                 :             : 
     105                 :             : void
     106                 :           0 : GncOptionGncOwnerValue::reset_default_value()
     107                 :             : {
     108                 :           0 :     gncOwnerCopy(m_default_value.get(), m_value.get());
     109                 :           0 : }
     110                 :             : 
     111                 :             : bool
     112                 :           0 : GncOptionGncOwnerValue::is_changed() const noexcept
     113                 :             : {
     114                 :           0 :     return gncOwnerEqual(m_value.get(), m_default_value.get());
     115                 :             : }
     116                 :             : 
     117                 :             : bool
     118                 :           0 : GncOptionGncOwnerValue::deserialize(const std::string& str) noexcept
     119                 :             : {
     120                 :             :     try {
     121                 :           0 :         auto guid{static_cast<GncGUID>(gnc::GUID::from_string(str))};
     122                 :           0 :         auto inst = qof_instance_from_guid(&guid, m_ui_type);
     123                 :           0 :         if (inst)
     124                 :             :         {
     125                 :           0 :             GncOwner owner{};
     126                 :           0 :             owner.type = ui_type_to_owner_type(m_ui_type);
     127                 :           0 :             owner.owner.undefined = inst;
     128                 :           0 :             set_default_value(&owner);
     129                 :           0 :             return true;
     130                 :             :         }
     131                 :             :     }
     132                 :           0 :     catch (const gnc::guid_syntax_exception& err)
     133                 :             :     {
     134                 :           0 :         PWARN("Failed to convert %s to a GUID", str.c_str());
     135                 :           0 :     }
     136                 :           0 :     return false;
     137                 :             : }
     138                 :             : 
     139                 :             : std::string
     140                 :           0 : GncOptionGncOwnerValue::serialize() const noexcept
     141                 :             : {
     142                 :             : 
     143                 :           0 :     auto owner{m_value.get()};
     144                 :           0 :     gnc::GUID guid{*qof_instance_get_guid(static_cast<QofInstance*>(owner->owner.undefined))};
     145                 :           0 :     std::string retval{guid.to_string()};
     146                 :             : 
     147                 :           0 :     return retval;
     148                 :             : }
     149                 :             : 
     150                 :             : static GncItem
     151                 :         165 : make_gnc_item(const QofInstance* inst)
     152                 :             : {
     153                 :         165 :     if (!inst)
     154                 :         108 :         return std::make_pair<QofIdTypeConst, GncGUID>("", guid_new_return());
     155                 :          57 :     auto type{qof_collection_get_type(qof_instance_get_collection(inst))};
     156                 :          57 :     auto guid{qof_instance_get_guid(inst)};
     157                 :          57 :     return std::make_pair(std::move(type), std::move(*const_cast<GncGUID*>(guid)));
     158                 :             : }
     159                 :             : 
     160                 :             : static inline QofBook*
     161                 :        3574 : get_current_book(void)
     162                 :             : {
     163                 :        3574 :     return qof_session_get_book(gnc_get_current_session());
     164                 :             : }
     165                 :             : 
     166                 :             : static inline Account*
     167                 :         261 : get_current_root_account(void)
     168                 :             : {
     169                 :         261 :     return gnc_book_get_root_account(get_current_book());
     170                 :             : }
     171                 :             : 
     172                 :             : static const QofInstance*
     173                 :         264 : qof_instance_from_gnc_item(const GncItem& item)
     174                 :             : {
     175                 :         264 :     auto [type, guid] = item;
     176                 :         264 :     auto book{get_current_book()};
     177                 :         264 :     auto coll{qof_book_get_collection(book, type)};
     178                 :         528 :     return static_cast<QofInstance*>(qof_collection_lookup_entity(coll, &guid));
     179                 :             : }
     180                 :             : 
     181                 :          67 : GncOptionQofInstanceValue::GncOptionQofInstanceValue(
     182                 :             :     const char* section, const char* name,
     183                 :             :     const char* key, const char* doc_string,
     184                 :          67 :     const QofInstance* value, GncOptionUIType ui_type) :
     185                 :             :     OptionClassifier{section, name, key, doc_string},
     186                 :          67 :     m_ui_type(ui_type), m_value{},
     187                 :         335 :     m_default_value{} {
     188                 :          67 :     m_value = make_gnc_item(value);
     189                 :          67 :     m_default_value = make_gnc_item(value);
     190                 :          67 : }
     191                 :             : 
     192                 :          67 : GncOptionQofInstanceValue::GncOptionQofInstanceValue(const GncOptionQofInstanceValue& from) :
     193                 :         201 :     OptionClassifier{from.m_section, from.m_name, from.m_sort_tag,
     194                 :          67 :                      from.m_doc_string},
     195                 :          67 :     m_ui_type(from.get_ui_type()), m_value{from.get_item()},
     196                 :         134 :     m_default_value{from.get_default_item()}
     197                 :             : {
     198                 :          67 : }
     199                 :             : void
     200                 :          30 : GncOptionQofInstanceValue::set_value(const QofInstance* new_value)
     201                 :             : {
     202                 :          30 :     m_value = make_gnc_item(new_value);
     203                 :          30 :     m_dirty = true;
     204                 :          30 : }
     205                 :             : 
     206                 :             : void
     207                 :           1 : GncOptionQofInstanceValue::set_default_value(const QofInstance *new_value)
     208                 :             : {
     209                 :           1 :     m_value = m_default_value = make_gnc_item(new_value);
     210                 :             : 
     211                 :           1 : }
     212                 :             : 
     213                 :             : const QofInstance*
     214                 :         260 : GncOptionQofInstanceValue::get_value() const
     215                 :             : {
     216                 :         260 :     return qof_instance_from_gnc_item(m_value);
     217                 :             : }
     218                 :             : 
     219                 :             : const QofInstance*
     220                 :           4 : GncOptionQofInstanceValue::get_default_value() const
     221                 :             : {
     222                 :           4 :     return qof_instance_from_gnc_item(m_default_value);
     223                 :             : }
     224                 :             : 
     225                 :             : void
     226                 :           0 : GncOptionQofInstanceValue::reset_default_value()
     227                 :             : {
     228                 :           0 :     m_value = m_default_value;
     229                 :           0 : }
     230                 :             : 
     231                 :             : bool
     232                 :           0 : GncOptionQofInstanceValue::is_changed() const noexcept
     233                 :             : {
     234                 :           0 :     return m_value != m_default_value;
     235                 :             : }
     236                 :             : 
     237                 :             : bool
     238                 :           0 : GncOptionQofInstanceValue::deserialize(const std::string& str) noexcept
     239                 :             : {
     240                 :           0 :     QofInstance* inst{};
     241                 :             :     // Commodities are often serialized as Namespace::Mnemonic or just Mnemonic
     242                 :             :     try {
     243                 :           0 :         auto guid{static_cast<GncGUID>(gnc::GUID::from_string(str))};
     244                 :           0 :         inst = qof_instance_from_guid(&guid, m_ui_type);
     245                 :           0 :         if (inst)
     246                 :             :         {
     247                 :           0 :             m_value = make_gnc_item(inst);
     248                 :           0 :             return true;
     249                 :             :         }
     250                 :             :     }
     251                 :           0 :     catch (const gnc::guid_syntax_exception& err)
     252                 :             :     {
     253                 :           0 :         PWARN("Failed to convert %s to a GUID", str.c_str());
     254                 :           0 :     }
     255                 :           0 :     return false;
     256                 :             : }
     257                 :             : 
     258                 :             : std::string
     259                 :           4 : GncOptionQofInstanceValue::serialize() const noexcept
     260                 :             : {
     261                 :           4 :     auto inst{get_value()};
     262                 :           4 :     std::string retval;
     263                 :           4 :     if (GNC_IS_COMMODITY(inst))
     264                 :             :     {
     265                 :           1 :         auto commodity{GNC_COMMODITY(inst)};
     266                 :           1 :         if (!gnc_commodity_is_currency(commodity))
     267                 :             :         {
     268                 :           1 :             auto name_space{gnc_commodity_get_namespace(GNC_COMMODITY(inst))};
     269                 :           1 :             if (name_space && *name_space != '\0')
     270                 :             :             {
     271                 :           1 :                 retval = name_space;
     272                 :           1 :                 retval += ":";
     273                 :             :             }
     274                 :             :         }
     275                 :           1 :         retval += gnc_commodity_get_mnemonic(GNC_COMMODITY(inst));
     276                 :           1 :         return retval;
     277                 :             :     }
     278                 :             :     else
     279                 :             :     {
     280                 :           3 :         gnc::GUID guid{m_value.second};
     281                 :           3 :         retval = guid.to_string();
     282                 :             :     }
     283                 :           3 :     return retval;
     284                 :             : }
     285                 :             : 
     286                 :             : static gnc_commodity*
     287                 :        2748 : gnc_commodity_from_namespace_and_mnemonic(std::string_view name_space,
     288                 :             :                                           std::string_view mnemonic)
     289                 :             : {
     290                 :        2748 :     auto book{get_current_book()};
     291                 :        2748 :     auto table = gnc_commodity_table_get_table(book);
     292                 :        2748 :     return gnc_commodity_table_lookup(table, name_space.data(),
     293                 :        2748 :                                       mnemonic.data());
     294                 :             : }
     295                 :             : 
     296                 :             : gnc_commodity*
     297                 :        2741 : GncOptionCommodityValue::get_value() const
     298                 :             : {
     299                 :        2741 :     return gnc_commodity_from_namespace_and_mnemonic(m_namespace, m_mnemonic);
     300                 :             : }
     301                 :             : 
     302                 :             : gnc_commodity*
     303                 :           4 : GncOptionCommodityValue::get_default_value() const
     304                 :             : {
     305                 :           4 :     return gnc_commodity_from_namespace_and_mnemonic(m_default_namespace,
     306                 :           4 :                                                      m_default_mnemonic);
     307                 :             : }
     308                 :             : 
     309                 :             : void
     310                 :        2796 : GncOptionCommodityValue::set_value(gnc_commodity* value)
     311                 :             : {
     312                 :        2796 :     if (!validate(value))
     313                 :           1 :         throw std::invalid_argument("Value not a currency when required or not a commodity. Value not set.");
     314                 :        2795 :     m_mnemonic = gnc_commodity_get_mnemonic(value);
     315                 :        2795 :     m_namespace = gnc_commodity_get_namespace(value);
     316                 :        2795 :     m_dirty = true;
     317                 :        2795 : }
     318                 :             : 
     319                 :             : void
     320                 :           0 : GncOptionCommodityValue::set_default_value(gnc_commodity* value)
     321                 :             : {
     322                 :           0 :     if (!validate(value))
     323                 :           0 :         throw std::invalid_argument("Value not a currency when required or not a commodity. Value not set.");
     324                 :           0 :     m_mnemonic = m_default_mnemonic = gnc_commodity_get_mnemonic(value);
     325                 :           0 :     m_namespace = m_default_namespace = gnc_commodity_get_namespace(value);
     326                 :           0 : }
     327                 :             : 
     328                 :             : void
     329                 :           0 : GncOptionCommodityValue::reset_default_value()
     330                 :             : {
     331                 :           0 :     m_mnemonic = m_default_mnemonic;
     332                 :           0 :     m_namespace = m_default_namespace;
     333                 :           0 : }
     334                 :             : 
     335                 :             : bool
     336                 :         179 : GncOptionCommodityValue::is_changed() const noexcept
     337                 :             : {
     338                 :         179 :     return m_namespace != m_default_namespace || m_mnemonic != m_default_mnemonic;
     339                 :             : }
     340                 :             : 
     341                 :             : bool
     342                 :        5087 : GncOptionCommodityValue::validate(gnc_commodity* comm) const noexcept
     343                 :             : {
     344                 :        5087 :     if (!GNC_IS_COMMODITY(comm))
     345                 :           0 :         return false;
     346                 :        5087 :     if (m_is_currency && !gnc_commodity_is_currency(comm))
     347                 :           4 :         return false;
     348                 :        5083 :     return true;
     349                 :             : }
     350                 :             : 
     351                 :             : std::string
     352                 :           3 : GncOptionCommodityValue::serialize() const noexcept
     353                 :             : {
     354                 :           3 :     if (m_is_currency)
     355                 :           2 :         return m_mnemonic;
     356                 :             :     else
     357                 :           1 :         return m_namespace + ":" + m_mnemonic;
     358                 :             : }
     359                 :             : 
     360                 :             : bool
     361                 :           3 : GncOptionCommodityValue::deserialize(const std::string& str) noexcept
     362                 :             : {
     363                 :           3 :    auto sep{str.find(":")};
     364                 :           3 :     gnc_commodity* comm{};
     365                 :           3 :     std::string mnemonic, name_space;
     366                 :           3 :     if (sep != std::string::npos)
     367                 :             :     {
     368                 :           2 :         name_space = str.substr(0, sep);
     369                 :           2 :         mnemonic = str.substr(sep + 1, -1);
     370                 :             :     }
     371                 :             :     else
     372                 :             :     {
     373                 :           1 :         name_space = "CURRENCY";
     374                 :           1 :         mnemonic = str;
     375                 :             :     }
     376                 :           3 :     comm = gnc_commodity_from_namespace_and_mnemonic(name_space, mnemonic);
     377                 :           3 :     if (!validate(comm))
     378                 :           1 :         return false;
     379                 :           2 :     m_namespace = std::move(name_space);
     380                 :           2 :     m_mnemonic = std::move(mnemonic);
     381                 :           2 :     return true;
     382                 :           3 : }
     383                 :             : 
     384                 :             : bool
     385                 :        3045 : GncOptionAccountListValue::validate(const GncOptionAccountList& values) const
     386                 :             : {
     387                 :        3045 :     if (values.empty())
     388                 :          57 :         return true;
     389                 :        2989 :     if ((get_ui_type() == GncOptionUIType::ACCOUNT_SEL || !m_multiselect) &&
     390                 :           1 :         values.size() != 1)
     391                 :             :     {
     392                 :           1 :         PWARN("GncOptionAccountListValue::validate: Multiple values for a non-multiselect option.");
     393                 :           1 :         return false;
     394                 :             :     }
     395                 :        2987 :     if (m_allowed.empty())
     396                 :        2778 :         return true;
     397                 :         209 :     auto book{get_current_book()};
     398                 :         855 :     for(auto& guid : values)
     399                 :             :     {
     400                 :         725 :         if (std::find(m_allowed.begin(), m_allowed.end(),
     401                 :        1450 :                       xaccAccountGetType(xaccAccountLookup(&guid, book))) == m_allowed.end())
     402                 :             :         {
     403                 :          79 :             PWARN("GncOptionAccountListValue::validate: Account %s is not of an allowed type", gnc::GUID(guid).to_string().c_str());
     404                 :          79 :             return false; }
     405                 :             :     }
     406                 :         130 :     return true;
     407                 :             : }
     408                 :             : 
     409                 :             : GncOptionAccountList
     410                 :        2492 : GncOptionAccountListValue::get_value() const
     411                 :             : {
     412                 :        2492 :     return !m_value.empty() ? m_value : get_default_value();
     413                 :             : }
     414                 :             : 
     415                 :             : GncOptionAccountList
     416                 :        1049 : GncOptionAccountListValue::get_default_value() const
     417                 :             : {
     418                 :        1049 :     if (!m_default_value.empty())
     419                 :           4 :         return m_default_value;
     420                 :             : 
     421                 :             :     /* If no default has been set and there's an allowed set then find the first
     422                 :             :      * account that matches one of the allowed account types.
     423                 :             :      */
     424                 :        1045 :     GncOptionAccountList retval{};
     425                 :        1045 :     if (m_allowed.empty())
     426                 :         860 :         return retval;
     427                 :             : 
     428                 :         185 :     auto root{get_current_root_account()};
     429                 :         185 :     auto account_list{gnc_account_get_descendants_sorted(root)};
     430                 :         185 :     if (!account_list)
     431                 :         140 :         return retval;
     432                 :             : 
     433                 :          66 :     for (auto node = account_list; node; node = g_list_next (node))
     434                 :             :     {
     435                 :          65 :         if (std::find(m_allowed.begin(), m_allowed.end(),
     436                 :         130 :                       xaccAccountGetType(GNC_ACCOUNT(node->data))) != m_allowed.end())
     437                 :             :         {
     438                 :          44 :             retval.push_back(*qof_entity_get_guid(GNC_ACCOUNT(node->data)));
     439                 :          44 :             break;
     440                 :             :         }
     441                 :             :     }
     442                 :          45 :     g_list_free(account_list);
     443                 :          45 :     return retval;
     444                 :        1045 : }
     445                 :             : 
     446                 :             : bool
     447                 :         374 : GncOptionAccountListValue::is_changed() const noexcept
     448                 :             : {
     449                 :         374 :     return m_value != m_default_value;
     450                 :             : }
     451                 :             : 
     452                 :             : 
     453                 :             : 
     454                 :             : /**
     455                 :             :  * Create a GList of account types to pass to gnc_account_sel_set_acct_filters.
     456                 :             :  * gnc_account_sel_set_acct_filters copies the list so the intermediary caller
     457                 :             :  * is responsible for freeing the list.
     458                 :             :  *
     459                 :             :  * @return an allocated GList* or nullptr if the list is empty.
     460                 :             :  */
     461                 :             : GList*
     462                 :           0 : GncOptionAccountListValue::account_type_list() const noexcept
     463                 :             : {
     464                 :           0 :     if (m_allowed.empty())
     465                 :           0 :         return nullptr;
     466                 :           0 :     GList* retval{nullptr};
     467                 :           0 :     for (auto type : m_allowed)
     468                 :           0 :         retval = g_list_prepend(retval, GINT_TO_POINTER(type));
     469                 :           0 :     return g_list_reverse(retval);
     470                 :             : }
     471                 :             : 
     472                 :             : bool
     473                 :          36 : GncOptionAccountSelValue::validate(const Account* value) const
     474                 :             : {
     475                 :          36 :     if (m_allowed.empty() || !value)
     476                 :          33 :         return true;
     477                 :           3 :     if (std::find(m_allowed.begin(), m_allowed.end(),
     478                 :           6 :                   xaccAccountGetType(value)) == m_allowed.end())
     479                 :           0 :             return false;
     480                 :           3 :     return true;
     481                 :             : }
     482                 :             : 
     483                 :             : const Account*
     484                 :          87 : GncOptionAccountSelValue::get_value() const
     485                 :             : {
     486                 :          87 :     auto book{get_current_book()};
     487                 :          87 :     return guid_equal(guid_null(), &m_value) ? get_default_value() :
     488                 :          87 :            xaccAccountLookup(&m_value, book);
     489                 :             : }
     490                 :             : 
     491                 :             : const Account*
     492                 :          83 : GncOptionAccountSelValue::get_default_value() const
     493                 :             : {
     494                 :             : 
     495                 :          83 :     if (!guid_equal(guid_null(), &m_default_value))
     496                 :             :     {
     497                 :           0 :         auto book{get_current_book()};
     498                 :           0 :         return xaccAccountLookup(&m_default_value, book);
     499                 :             :     }
     500                 :             : 
     501                 :             :     /* If no default has been set and there's an allowed set then find the first
     502                 :             :      * account that matches one of the allowed account types.
     503                 :             :      */
     504                 :          83 :     if (m_allowed.empty())
     505                 :           7 :         return nullptr;
     506                 :             : 
     507                 :          76 :     const Account* retval{nullptr};
     508                 :          76 :     auto root{get_current_root_account()};
     509                 :          76 :     auto account_list{gnc_account_get_descendants_sorted(root)};
     510                 :          76 :     if (!account_list)
     511                 :          40 :         return nullptr;
     512                 :             : 
     513                 :         344 :     for (auto node = account_list; node; node = g_list_next (node))
     514                 :         338 :         if (std::find(m_allowed.begin(), m_allowed.end(),
     515                 :         676 :                       xaccAccountGetType(GNC_ACCOUNT(node->data))) != m_allowed.end())
     516                 :             :         {
     517                 :          30 :             retval = GNC_ACCOUNT(node->data);
     518                 :          30 :             break;
     519                 :             :         }
     520                 :          36 :     g_list_free(account_list);
     521                 :          36 :     return retval;
     522                 :             : }
     523                 :             : 
     524                 :             : 
     525                 :             : /**
     526                 :             :  * Create a GList of account types to pass to gnc_account_sel_set_acct_filters.
     527                 :             :  * gnc_account_sel_set_acct_filters copies the list so the intermediary caller
     528                 :             :  * is responsible for freeing the list.
     529                 :             :  *
     530                 :             :  * @return an allocated GList* or nullptr if the list is empty.
     531                 :             :  */
     532                 :             : GList*
     533                 :           0 : GncOptionAccountSelValue::account_type_list() const noexcept
     534                 :             : {
     535                 :           0 :     if (m_allowed.empty())
     536                 :           0 :         return nullptr;
     537                 :           0 :     GList* retval{nullptr};
     538                 :           0 :     for (auto type : m_allowed)
     539                 :           0 :         retval = g_list_prepend(retval, GINT_TO_POINTER(type));
     540                 :           0 :     return g_list_reverse(retval);
     541                 :             : }
     542                 :             : 
     543                 :             : bool
     544                 :         255 : GncOptionDateValue::validate(RelativeDatePeriod value) {
     545                 :         255 :     if (m_period_set.empty())
     546                 :          27 :         return true; // No restrictions
     547                 :         228 :     if (std::find(m_period_set.begin(), m_period_set.end(),
     548                 :         456 :                   value) != m_period_set.end())
     549                 :         226 :         return true;
     550                 :           2 :     return false;
     551                 :             : }
     552                 :             : 
     553                 :             : time64
     554                 :        4964 : GncOptionDateValue::get_value() const noexcept
     555                 :             : {
     556                 :        4964 :     if (m_period == RelativeDatePeriod::ABSOLUTE)
     557                 :        4951 :         return m_date;
     558                 :          13 :     return gnc_relative_date_to_time64(m_period);
     559                 :             : }
     560                 :             : 
     561                 :             : time64
     562                 :           0 : GncOptionDateValue::get_default_value() const noexcept
     563                 :             : {
     564                 :           0 :     if (m_default_period == RelativeDatePeriod::ABSOLUTE)
     565                 :           0 :         return m_default_date;
     566                 :           0 :     return gnc_relative_date_to_time64(m_default_period);
     567                 :             : }
     568                 :             : 
     569                 :             : /* Use asserts for pre- and post-conditions to deliberately crash if they're not
     570                 :             :  * met as the program design should prevent that from happening.
     571                 :             :  */
     572                 :             : uint16_t
     573                 :           4 : GncOptionDateValue::get_period_index() const noexcept
     574                 :             : {
     575                 :           4 :     assert (m_period != RelativeDatePeriod::ABSOLUTE);
     576                 :           4 :     assert(!m_period_set.empty());
     577                 :           4 :     auto item{std::find(m_period_set.begin(), m_period_set.end(), m_period)};
     578                 :           4 :     assert(item != m_period_set.end());
     579                 :           4 :     return item - m_period_set.begin();
     580                 :             : }
     581                 :             : 
     582                 :             : uint16_t
     583                 :           0 : GncOptionDateValue::get_default_period_index() const noexcept
     584                 :             : {
     585                 :           0 :     assert(m_period != RelativeDatePeriod::ABSOLUTE);
     586                 :           0 :     assert(!m_period_set.empty());
     587                 :           0 :     auto item{std::find(m_period_set.begin(), m_period_set.end(),
     588                 :           0 :                         m_default_period)};
     589                 :           0 :     assert (item != m_period_set.end());
     590                 :           0 :     return item - m_period_set.begin();
     591                 :             : }
     592                 :             : 
     593                 :             : void
     594                 :           2 : GncOptionDateValue::set_value(uint16_t index) noexcept
     595                 :             : {
     596                 :           2 :     assert(!m_period_set.empty());
     597                 :           2 :     assert(index < m_period_set.size());
     598                 :           2 :     m_date = INT64_MAX;
     599                 :           2 :     m_period = m_period_set[index];
     600                 :           2 :     m_dirty = true;
     601                 :           2 : }
     602                 :             : 
     603                 :             : uint16_t
     604                 :           0 : GncOptionDateValue::permissible_value_index(const char* key) const noexcept
     605                 :             : {
     606                 :           0 :     auto index = std::find_if(m_period_set.begin(), m_period_set.end(),
     607                 :           0 :                               [key](auto period) -> bool {
     608                 :           0 :                                   return strcmp(gnc_relative_date_display_string(period),
     609                 :           0 :                                                 key) == 0;
     610                 :             :                               });
     611                 :           0 :     return index != m_period_set.end() ? index - m_period_set.begin() : 0;
     612                 :             : }
     613                 :             : 
     614                 :             : static const char* date_type_str[] {"absolute", "relative"};
     615                 :             : 
     616                 :             : std::ostream&
     617                 :           0 : GncOptionDateValue::out_stream(std::ostream& oss) const noexcept
     618                 :             : {
     619                 :           0 :     if (m_period == RelativeDatePeriod::ABSOLUTE)
     620                 :           0 :         oss << date_type_str[0] << " . " << m_date;
     621                 :             :     else
     622                 :             :         oss << date_type_str[1] << " . " <<
     623                 :           0 :             gnc_relative_date_storage_string(m_period);
     624                 :           0 :     return oss;
     625                 :             : }
     626                 :             : 
     627                 :             : std::istream&
     628                 :          13 : GncOptionDateValue::in_stream(std::istream& iss)
     629                 :             : {
     630                 :             :     char type_str[10]; //The length of both "absolute" and "relative" plus 1.
     631                 :          13 :     iss.getline(type_str, sizeof(type_str), '.');
     632                 :          13 :     if(!iss)
     633                 :           0 :         throw std::invalid_argument("Date Type separator missing");
     634                 :             :     /* strcmp is safe, istream::getline null terminates the buffer. */
     635                 :          13 :     if (strcmp(type_str, "absolute ") == 0)
     636                 :             :     {
     637                 :             :         time64 time;
     638                 :           1 :         iss >> time;
     639                 :           1 :         set_value(time);
     640                 :           1 :         if (iss.get() != ')')
     641                 :           1 :             iss.unget();
     642                 :             :     }
     643                 :          12 :     else if (strcmp(type_str, "relative ") == 0)
     644                 :             :     {
     645                 :          12 :         std::string period_str;
     646                 :          12 :         iss >> period_str;
     647                 :          12 :         if (period_str.back() == ')')
     648                 :           0 :             period_str.pop_back();
     649                 :          12 :         auto period = gnc_relative_date_from_storage_string(period_str.c_str());
     650                 :          12 :         if (period == RelativeDatePeriod::ABSOLUTE)
     651                 :             :         {
     652                 :           0 :             std::string err{"Unknown period string in date option: '"};
     653                 :           0 :             err += period_str;
     654                 :           0 :             err += "'";
     655                 :           0 :             throw std::invalid_argument(err);
     656                 :           0 :         }
     657                 :             : 
     658                 :          12 :         set_value(period);
     659                 :          12 :     }
     660                 :             :     else
     661                 :             :     {
     662                 :           0 :         std::string err{"Unknown date type string in date option: '"};
     663                 :           0 :         err += type_str;
     664                 :           0 :         err += "'";
     665                 :           0 :         throw std::invalid_argument{err};
     666                 :           0 :     }
     667                 :          13 :     return iss;
     668                 :             : }
     669                 :             : 
     670                 :             : QofInstance*
     671                 :           5 : qof_instance_from_guid(GncGUID* guid, GncOptionUIType type)
     672                 :             : {
     673                 :             :     QofIdType qof_type;
     674                 :           5 :     switch(type)
     675                 :             :     {
     676                 :           1 :         case GncOptionUIType::BUDGET:
     677                 :           1 :             qof_type = "Budget";
     678                 :           1 :             break;
     679                 :           0 :         case GncOptionUIType::JOB:
     680                 :           0 :             qof_type = "gncJob";
     681                 :           0 :             break;
     682                 :           0 :         case GncOptionUIType::CUSTOMER:
     683                 :           0 :             qof_type = "gncCustomer";
     684                 :           0 :             break;
     685                 :           0 :         case GncOptionUIType::VENDOR:
     686                 :           0 :             qof_type = "gncVendor";
     687                 :           0 :             break;
     688                 :           0 :         case GncOptionUIType::EMPLOYEE:
     689                 :           0 :             qof_type = "gncEmployee";
     690                 :           0 :             break;
     691                 :           0 :         case GncOptionUIType::INVOICE:
     692                 :           0 :             qof_type = "gncInvoice";
     693                 :           0 :             break;
     694                 :           0 :         case GncOptionUIType::TAX_TABLE:
     695                 :           0 :             qof_type = "gncTaxTable";
     696                 :           0 :             break;
     697                 :           4 :         case GncOptionUIType::ACCOUNT_LIST:
     698                 :             :         case GncOptionUIType::ACCOUNT_SEL:
     699                 :             :         default:
     700                 :           4 :             qof_type = "Account";
     701                 :           4 :             break;
     702                 :             :     }
     703                 :           5 :     auto book{get_current_book()};
     704                 :           5 :     auto col{qof_book_get_collection(book, qof_type)};
     705                 :           5 :     return QOF_INSTANCE(qof_collection_lookup_entity(col, guid));
     706                 :             : }
     707                 :             : 
     708                 :             : QofInstance*
     709                 :           5 : qof_instance_from_string(const std::string& str, GncOptionUIType type)
     710                 :             : {
     711                 :           5 :     QofInstance* retval{nullptr};
     712                 :             :     try {
     713                 :           5 :         auto guid{static_cast<GncGUID>(gnc::GUID::from_string(str))};
     714                 :           5 :         retval = qof_instance_from_guid(&guid, type);
     715                 :             :     }
     716                 :           0 :     catch (const gnc::guid_syntax_exception& err)
     717                 :             :     {
     718                 :           0 :         PWARN("Failed to convert %s to a GUID", str.c_str());
     719                 :           0 :     }
     720                 :           5 :     return retval;
     721                 :             : }
     722                 :             : 
     723                 :             : std::string
     724                 :           1 : qof_instance_to_string(const QofInstance* inst)
     725                 :             : {
     726                 :           1 :     std::string retval;
     727                 :           1 :     gnc::GUID guid{*qof_instance_get_guid(inst)};
     728                 :           1 :     retval = guid.to_string();
     729                 :           2 :     return retval;
     730                 :           0 : }
     731                 :             : 
     732                 :             : template <typename ValueType> void
     733                 :       16802 : GncOptionValue<ValueType>::set_value(ValueType new_value)
     734                 :             : {
     735                 :       16802 :     m_value = new_value;
     736                 :       16802 :     m_dirty = true;
     737                 :       16802 : }
     738                 :             : 
     739                 :             : template <typename ValueType> void
     740                 :         126 : GncOptionValue<ValueType>::set_default_value(ValueType new_value)
     741                 :             : {
     742                 :         126 :     m_value = m_default_value = new_value;
     743                 :         126 : }
     744                 :             : 
     745                 :             : template <typename ValueType> void
     746                 :           0 : GncOptionValue<ValueType>::reset_default_value()
     747                 :             : {
     748                 :           0 :     m_value = m_default_value;
     749                 :           0 : }
     750                 :             : 
     751                 :             : /* Missing on purpose: QofQuery because for current usage it's serialized with
     752                 :             :  * gnc_query2scm. The future is to replace QofQuery with SQL queries so there's
     753                 :             :  * not much point to spending the time to create a std::string serialization for
     754                 :             :  * them.
     755                 :             :  */
     756                 :             : template <typename ValueType> std::string
     757                 :          12 : GncOptionValue<ValueType>::serialize() const noexcept
     758                 :             : {
     759                 :          20 :     static const std::string no_value{"No Value"};
     760                 :             :     if constexpr(std::is_same_v<ValueType, const QofInstance*>)
     761                 :             :         return m_value ? qof_instance_to_string(m_value) : no_value;
     762                 :             :     if constexpr(std::is_same_v<ValueType, const GncOwner*>)
     763                 :             :     {
     764                 :           0 :         if (!m_value)
     765                 :           0 :             return no_value;
     766                 :           0 :         auto guid{qof_instance_to_string(qofOwnerGetOwner(m_value))};
     767                 :           0 :         auto type{qofOwnerGetType(m_value)};
     768                 :           0 :         std::ostringstream ostr{};
     769                 :           0 :         ostr << type << " " << guid;
     770                 :           0 :         return ostr.str();
     771                 :           0 :     }
     772                 :             :     if constexpr(std::is_same_v<ValueType, GncOptionReportPlacementVec>)
     773                 :             :     {
     774                 :           0 :         std::ostringstream ostr{};
     775                 :           0 :         ostr << "'(";
     776                 :           0 :         std::for_each(m_value.begin(), m_value.end(),
     777                 :           0 :                  [&ostr](auto rp){
     778                 :           0 :                     auto [id, wide, high] = rp;
     779                 :           0 :                     ostr << "(" << id << " " << wide << " " << high << " #f) ";
     780                 :             :                  });
     781                 :           0 :         ostr << ")";
     782                 :           0 :         return ostr.str();
     783                 :           0 :     }
     784                 :             :     else if constexpr(is_same_decayed_v<ValueType, std::string>)
     785                 :           9 :         return m_value;
     786                 :             :     else if constexpr(is_same_decayed_v<ValueType, bool>)
     787                 :           4 :         return m_value ? "True" : "False";
     788                 :             :     else if constexpr(std::is_arithmetic_v<ValueType>)
     789                 :           1 :         return std::to_string(m_value);
     790                 :             :     else
     791                 :           0 :         return "Serialization not implemented";
     792                 :             : }
     793                 :             : 
     794                 :             : template <typename ValueType> bool
     795                 :           0 : GncOptionValue<ValueType>::deserialize(const std::string& str) noexcept
     796                 :             : {
     797                 :             :     if constexpr(std::is_same_v<ValueType, const QofInstance*>)
     798                 :             :         set_value(qof_instance_from_string(str, get_ui_type()));
     799                 :             :     if constexpr(std::is_same_v<ValueType, const GncOwner*>)
     800                 :             :     {
     801                 :           0 :         std::istringstream istr{str};
     802                 :           0 :         std::string type, guid;
     803                 :           0 :         istr >> type >> guid;
     804                 :           0 :         auto inst{qof_instance_from_string(guid, get_ui_type())};
     805                 :           0 :         qofOwnerSetEntity(const_cast<GncOwner*>(m_value), inst);
     806                 :           0 :     }
     807                 :             :     if constexpr(std::is_same_v<ValueType, GncOptionReportPlacementVec>)
     808                 :             :     {
     809                 :           0 :         std::istringstream istr{str};
     810                 :           0 :         GncOptionReportPlacementVec rpv;
     811                 :           0 :         while (istr)
     812                 :             :         {
     813                 :             :             uint32_t id, wide, high;
     814                 :           0 :             istr >> id >> wide >> high;
     815                 :           0 :             rpv.emplace_back(id, wide, high);
     816                 :             :         }
     817                 :           0 :         set_value(rpv);
     818                 :           0 :     }
     819                 :             :     else if constexpr(is_same_decayed_v<ValueType, std::string>)
     820                 :           0 :         set_value(str);
     821                 :             :     else if constexpr(is_same_decayed_v<ValueType, bool>)
     822                 :           0 :         set_value(str == "True");
     823                 :             :     else if constexpr(is_same_decayed_v<ValueType, int>)
     824                 :           0 :         set_value(stoi(str));
     825                 :             :     else if constexpr(is_same_decayed_v<ValueType, int64_t>)
     826                 :           0 :         set_value(stoll(str));
     827                 :             :     else if constexpr(is_same_decayed_v<ValueType, double>)
     828                 :           0 :         set_value(stod(str));
     829                 :             :     else
     830                 :           0 :         return false;
     831                 :           0 :     return true;
     832                 :             : }
     833                 :             : 
     834                 :             : std::string
     835                 :           3 : GncOptionAccountListValue::serialize() const noexcept
     836                 :             : {
     837                 :           7 :     static const std::string no_value{"No Value"};
     838                 :           3 :     std::string retval;
     839                 :           3 :     bool first = true;
     840                 :           3 :     if (m_value.empty())
     841                 :           0 :         return no_value;
     842                 :             :     gchar guidstr[GUID_ENCODING_LENGTH + 1];
     843                 :           8 :     for (auto val : m_value)
     844                 :             :     {
     845                 :           5 :         if (!first)
     846                 :           2 :             retval += " ";
     847                 :           5 :         first = false;
     848                 :           5 :         guid_to_string_buff (&val, guidstr);
     849                 :           5 :         retval += guidstr;
     850                 :             :     }
     851                 :           3 :     return retval;
     852                 :           3 : }
     853                 :             : 
     854                 :             : bool
     855                 :           0 : GncOptionAccountListValue::deserialize(const std::string& str) noexcept
     856                 :             : {
     857                 :           0 :     if (str.empty() || str.size() < GUID_ENCODING_LENGTH)
     858                 :           0 :         return false;
     859                 :           0 :     m_value.clear();
     860                 :           0 :     m_value.reserve(str.size() / GUID_ENCODING_LENGTH);
     861                 :           0 :     bool first = true;
     862                 :           0 :     size_t pos{};
     863                 :           0 :     while (pos + GUID_ENCODING_LENGTH < str.size())
     864                 :             :     {
     865                 :           0 :         if (!first)
     866                 :           0 :             ++pos;
     867                 :           0 :         first = false;
     868                 :           0 :         GncGUID guid{};
     869                 :           0 :         string_to_guid(str.substr(pos, pos + GUID_ENCODING_LENGTH).c_str(), &guid);
     870                 :           0 :         m_value.push_back(guid);
     871                 :           0 :         pos += GUID_ENCODING_LENGTH;
     872                 :             :     }
     873                 :           0 :     return true;
     874                 :             : }
     875                 :             : 
     876                 :             : std::string
     877                 :           2 : GncOptionAccountSelValue::serialize() const noexcept
     878                 :             : {
     879                 :           4 :     static const std::string no_value{"No Value"};
     880                 :           2 :     if (guid_equal(guid_null(), &m_value))
     881                 :           0 :         return no_value;
     882                 :             : 
     883                 :             :     gchar strbuff[GUID_ENCODING_LENGTH + 1];
     884                 :           2 :     guid_to_string_buff (&m_value, strbuff);
     885                 :           4 :     return strbuff;
     886                 :             : }
     887                 :             : 
     888                 :             : bool
     889                 :           0 : GncOptionAccountSelValue::deserialize(const std::string& str) noexcept
     890                 :             : {
     891                 :           0 :     set_value(reinterpret_cast<Account*>(qof_instance_from_string(str, get_ui_type())));
     892                 :           0 :     return true;
     893                 :             : }
     894                 :             : 
     895                 :             : std::string
     896                 :           8 : GncOptionMultichoiceValue::serialize() const noexcept
     897                 :             : {
     898                 :          12 :     static const std::string no_value{""};
     899                 :           8 :     std::string retval;
     900                 :           8 :     bool first = true;
     901                 :           8 :     bool list_context = m_ui_type == GncOptionUIType::LIST;
     902                 :           8 :     if (m_value.empty())
     903                 :           0 :         return no_value;
     904                 :             : 
     905                 :           8 :     if (list_context)
     906                 :           2 :         retval += '(';
     907                 :          17 :     for (auto index : m_value)
     908                 :             :     {
     909                 :           9 :         if (!first)
     910                 :           1 :             retval += " ";
     911                 :           9 :         first = false;
     912                 :           9 :         retval += std::get<0>(m_choices[index]);
     913                 :             :     }
     914                 :           8 :     if (list_context)
     915                 :           2 :         retval += ')';
     916                 :           8 :     return retval;
     917                 :           8 : }
     918                 :             : 
     919                 :             : bool
     920                 :           0 : GncOptionMultichoiceValue::deserialize(const std::string& str) noexcept
     921                 :             : {
     922                 :             :     static const auto uint16_t_max = std::numeric_limits<uint16_t>::max();
     923                 :           0 :     if (str.empty())
     924                 :             : 
     925                 :           0 :         return false;
     926                 :           0 :     uint16_t pos{};
     927                 :           0 :     while (pos < str.size())
     928                 :             :     {
     929                 :           0 :         auto endpos{str.find(' ', pos)};
     930                 :           0 :         if (endpos == std::string::npos)
     931                 :           0 :             endpos = str.size();
     932                 :             :         //need a null-terminated char* to pass to permissible_value_index
     933                 :           0 :         auto index{permissible_value_index(str.substr(pos, endpos).c_str())};
     934                 :           0 :         if (index == uint16_t_max)
     935                 :           0 :             return false;
     936                 :           0 :         m_value.push_back(index);
     937                 :           0 :         pos = endpos + 1;
     938                 :             :     }
     939                 :           0 :     return true;
     940                 :             : }
     941                 :             : 
     942                 :             : template <typename ValueType> std::string
     943                 :           4 : GncOptionRangeValue<ValueType>::serialize() const noexcept
     944                 :             : {
     945                 :             :     if constexpr (std::is_arithmetic_v<ValueType>)
     946                 :             :     {
     947                 :           4 :         std::ostringstream ostr;
     948                 :             :         if constexpr(is_same_decayed_v<ValueType, double>)
     949                 :           2 :             ostr << std::showpoint << std::fixed;
     950                 :           4 :         ostr << m_value;
     951                 :           4 :         return ostr.str();
     952                 :           4 :     }
     953                 :             :     return "";
     954                 :             : }
     955                 :             : 
     956                 :             : template <typename ValueType> bool
     957                 :           0 : GncOptionRangeValue<ValueType>::deserialize(const std::string& str) noexcept
     958                 :             : {
     959                 :             :     if constexpr(is_same_decayed_v<ValueType, int>)
     960                 :           0 :         set_value(stoi(str));
     961                 :             :     else if constexpr(is_same_decayed_v<ValueType, double>)
     962                 :           0 :         set_value(stod(str));
     963                 :           0 :     return true;
     964                 :             : }
     965                 :             : 
     966                 :             : std::string
     967                 :          20 : GncOptionDateValue::serialize() const noexcept
     968                 :             : {
     969                 :          20 :     std::string retval{"("};
     970                 :          20 :     if (m_period == RelativeDatePeriod::ABSOLUTE)
     971                 :             :     {
     972                 :           3 :         retval += date_type_str[0];
     973                 :           3 :         retval += " . ";
     974                 :           3 :         retval += std::to_string(m_date);
     975                 :             :     }
     976                 :             :     else
     977                 :             :     {
     978                 :          17 :         retval += date_type_str[1];
     979                 :          17 :         retval +=  " . ";
     980                 :          17 :         retval += gnc_relative_date_storage_string(m_period);
     981                 :             :     }
     982                 :          20 :     retval += ")";
     983                 :          20 :     return retval;
     984                 :             : }
     985                 :             : 
     986                 :             : bool
     987                 :           0 : GncOptionDateValue::deserialize(const std::string& str) noexcept
     988                 :             : {
     989                 :             :  //The length of both "absolute" and "relative".
     990                 :             :     static constexpr size_t date_type_len{9};
     991                 :             :     // date_type_len plus the length of " . ".
     992                 :             :     static constexpr size_t date_value_pos{12};
     993                 :           0 :     auto type_str{str.substr(0, date_type_len)};
     994                 :           0 :     auto period_str{str.substr(date_value_pos)};
     995                 :           0 :     if (type_str == "absolute")
     996                 :             :     {
     997                 :             :         // Need a cast to disambiguate from time64.
     998                 :           0 :         set_value(static_cast<uint16_t>(std::stoll(period_str)));
     999                 :           0 :         return true;
    1000                 :             :     }
    1001                 :           0 :     else if (type_str == "relative ")
    1002                 :             :     {
    1003                 :           0 :         auto period = gnc_relative_date_from_storage_string(period_str.c_str());
    1004                 :           0 :         if (period == RelativeDatePeriod::ABSOLUTE)
    1005                 :             :         {
    1006                 :           0 :             PWARN("Unknown period string in date option: '%s'",
    1007                 :             :                   period_str.c_str());
    1008                 :           0 :             return false;
    1009                 :             :         }
    1010                 :             : 
    1011                 :           0 :         set_value(period);
    1012                 :           0 :         return true;
    1013                 :             :     }
    1014                 :             :     else
    1015                 :             :     {
    1016                 :           0 :         PWARN("Unknown date type string in date option: '%s'",
    1017                 :             :               type_str.c_str());
    1018                 :           0 :         return false;
    1019                 :             :     }
    1020                 :           0 : }
    1021                 :             : 
    1022                 :             : std::istream&
    1023                 :           3 : operator>> (std::istream& iss, GncOptionCommodityValue& opt)
    1024                 :             : {
    1025                 :           3 :     std::string instr;
    1026                 :           3 :     iss >> instr;
    1027                 :           3 :     if (!opt.deserialize(instr))
    1028                 :           1 :         throw std::invalid_argument("Invalid commodity string in stream.");
    1029                 :           2 :     return iss;
    1030                 :           3 : }
    1031                 :             : 
    1032                 :             : template void GncOptionValue<bool>::set_value(bool);
    1033                 :             : template void GncOptionValue<int>::set_value(int);
    1034                 :             : template void GncOptionValue<int64_t>::set_value(int64_t);
    1035                 :             : template void GncOptionValue<double>::set_value(double);
    1036                 :             : template void GncOptionValue<char*>::set_value(char*);
    1037                 :             : template void GncOptionValue<const char*>::set_value(const char*);
    1038                 :             : template void GncOptionValue<std::string>::set_value(std::string);
    1039                 :             : template void GncOptionValue<const QofQuery*>::set_value(const QofQuery*);
    1040                 :             : template void GncOptionValue<const GncOwner*>::set_value(const GncOwner*);
    1041                 :             : template void GncOptionValue<RelativeDatePeriod>::set_value(RelativeDatePeriod);
    1042                 :             : template void GncOptionValue<uint16_t>::set_value(uint16_t);
    1043                 :             : template void GncOptionValue<GncOptionAccountList>::set_value(GncOptionAccountList);
    1044                 :             : template void GncOptionValue<GncMultichoiceOptionIndexVec>::set_value(GncMultichoiceOptionIndexVec);
    1045                 :             : template void GncOptionValue<GncOptionReportPlacementVec>::set_value(GncOptionReportPlacementVec);
    1046                 :             : template void GncOptionValue<GncOptionDateFormat>::set_value(GncOptionDateFormat);
    1047                 :             : template void GncOptionValue<bool>::set_default_value(bool);
    1048                 :             : template void GncOptionValue<int>::set_default_value(int);
    1049                 :             : template void GncOptionValue<int64_t>::set_default_value(int64_t);
    1050                 :             : template void GncOptionValue<double>::set_default_value(double);
    1051                 :             : template void GncOptionValue<char*>::set_default_value(char*);
    1052                 :             : template void GncOptionValue<const char*>::set_default_value(const char*);
    1053                 :             : template void GncOptionValue<std::string>::set_default_value(std::string);
    1054                 :             : template void GncOptionValue<const QofQuery*>::set_default_value(const QofQuery*);
    1055                 :             : template void GncOptionValue<const GncOwner*>::set_default_value(const GncOwner*);
    1056                 :             : template void GncOptionValue<RelativeDatePeriod>::set_default_value(RelativeDatePeriod);
    1057                 :             : template void GncOptionValue<uint16_t>::set_default_value(uint16_t);
    1058                 :             : template void GncOptionValue<GncOptionAccountList>::set_default_value(GncOptionAccountList);
    1059                 :             : template void GncOptionValue<GncMultichoiceOptionIndexVec>::set_default_value(GncMultichoiceOptionIndexVec);
    1060                 :             : template void GncOptionValue<GncOptionReportPlacementVec>::set_default_value(GncOptionReportPlacementVec);
    1061                 :             : template void GncOptionValue<GncOptionDateFormat>::set_default_value(GncOptionDateFormat);
    1062                 :             : template void GncOptionValue<bool>::reset_default_value();
    1063                 :             : template void GncOptionValue<int>::reset_default_value();
    1064                 :             : template void GncOptionValue<int64_t>::reset_default_value();
    1065                 :             : template void GncOptionValue<double>::reset_default_value();
    1066                 :             : template void GncOptionValue<char*>::reset_default_value();
    1067                 :             : template void GncOptionValue<const char*>::reset_default_value();
    1068                 :             : template void GncOptionValue<std::string>::reset_default_value();
    1069                 :             : template void GncOptionValue<const QofQuery*>::reset_default_value();
    1070                 :             : template void GncOptionValue<const GncOwner*>::reset_default_value();
    1071                 :             : template void GncOptionValue<RelativeDatePeriod>::reset_default_value();
    1072                 :             : template void GncOptionValue<uint16_t>::reset_default_value();
    1073                 :             : template void GncOptionValue<GncOptionAccountList>::reset_default_value();
    1074                 :             : template void GncOptionValue<GncMultichoiceOptionIndexVec>::reset_default_value();
    1075                 :             : template void GncOptionValue<GncOptionReportPlacementVec>::reset_default_value();
    1076                 :             : template void GncOptionValue<GncOptionDateFormat>::reset_default_value();
    1077                 :             : template std::string GncOptionValue<bool>::serialize() const noexcept;
    1078                 :             : template std::string GncOptionValue<int>::serialize() const noexcept;
    1079                 :             : template std::string GncOptionValue<int64_t>::serialize() const noexcept;
    1080                 :             : template std::string GncOptionValue<double>::serialize() const noexcept;
    1081                 :             : template std::string GncOptionValue<char*>::serialize() const noexcept;
    1082                 :             : template std::string GncOptionValue<const char*>::serialize() const noexcept;
    1083                 :             : template std::string GncOptionValue<std::string>::serialize() const noexcept;
    1084                 :             : template std::string GncOptionValue<const QofQuery*>::serialize() const noexcept;
    1085                 :             : template std::string GncOptionValue<const GncOwner*>::serialize() const noexcept;
    1086                 :             : template std::string GncOptionValue<GncOptionReportPlacementVec>::serialize() const noexcept;
    1087                 :             : template std::string GncOptionValue<GncOptionDateFormat>::serialize() const noexcept;
    1088                 :             : template std::string GncOptionRangeValue<int>::serialize() const noexcept;
    1089                 :             : template std::string GncOptionRangeValue<double>::serialize() const noexcept;
    1090                 :             : template bool GncOptionValue<bool>::deserialize(const std::string&) noexcept;
    1091                 :             : template bool GncOptionValue<int>::deserialize(const std::string&) noexcept;
    1092                 :             : template bool GncOptionValue<int64_t>::deserialize(const std::string&) noexcept;
    1093                 :             : template bool GncOptionValue<double>::deserialize(const std::string&) noexcept;
    1094                 :             : template bool GncOptionValue<char*>::deserialize(const std::string&) noexcept;
    1095                 :             : template bool GncOptionValue<const char*>::deserialize(const std::string&) noexcept;
    1096                 :             : template bool GncOptionValue<std::string>::deserialize(const std::string&) noexcept;
    1097                 :             : template bool GncOptionValue<const QofQuery*>::deserialize(const std::string&) noexcept;
    1098                 :             : template bool GncOptionValue<const GncOwner*>::deserialize(const std::string&) noexcept;
    1099                 :             : template bool GncOptionValue<GncOptionReportPlacementVec>::deserialize(const std::string&) noexcept;
    1100                 :             : template bool GncOptionValue<GncOptionDateFormat>::deserialize(const std::string&) noexcept;
    1101                 :             : template bool GncOptionRangeValue<int>::deserialize(const std::string&) noexcept;
    1102                 :             : template bool GncOptionRangeValue<double>::deserialize(const std::string&) noexcept;
        

Generated by: LCOV version 2.0-1