2019-08-06 17:03:48 -05:00
/********************************************************************\
* gnc - optiondb . cpp - - Collection of GncOption objects *
* Copyright ( C ) 2019 John Ralls < jralls @ ceridwen . us > *
* *
* This program is free software ; you can redistribute it and / or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation ; either version 2 of *
* the License , or ( at your option ) any later version . *
* *
* This program is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY ; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU General Public License for more details . *
* *
* You should have received a copy of the GNU General Public License *
* along with this program ; if not , contact : *
* *
* Free Software Foundation Voice : + 1 - 617 - 542 - 5942 *
* 51 Franklin Street , Fifth Floor Fax : + 1 - 617 - 542 - 2652 *
* Boston , MA 02110 - 1301 , USA gnu @ gnu . org *
* *
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2021-08-12 16:29:56 -05:00
# include <functional>
2020-01-27 15:40:39 -06:00
# include <string>
2019-12-05 20:00:07 -06:00
# include <limits>
# include <sstream>
2022-08-23 11:22:56 -05:00
# include "kvp-value.hpp"
# include "qofbookslots.h"
# include "guid.hpp"
2020-03-26 19:43:52 -05:00
# include "gnc-optiondb.h"
2020-01-27 15:40:39 -06:00
# include "gnc-optiondb.hpp"
# include "gnc-optiondb-impl.hpp"
2020-02-11 15:35:27 -06:00
# include "gnc-option-ui.hpp"
2019-08-06 17:03:48 -05:00
2022-08-23 11:22:56 -05:00
# include "gnc-session.h"
2020-03-26 19:43:52 -05:00
constexpr const char * log_module { G_LOG_DOMAIN } ;
constexpr auto stream_max = std : : numeric_limits < std : : streamsize > : : max ( ) ;
2020-10-06 12:09:27 -05:00
using AliasedOption = std : : pair < const char * , const char * > ;
using OptionAlias = std : : pair < const char * , AliasedOption > ;
using OptionAliases = std : : vector < OptionAlias > ;
class Aliases
{
static const OptionAliases c_option_aliases ;
public :
static const AliasedOption * find_alias ( const char * old_name )
{
if ( ! old_name ) return nullptr ;
const auto alias =
std : : find_if ( c_option_aliases . begin ( ) , c_option_aliases . end ( ) ,
[ old_name ] ( auto alias ) {
return std : : strcmp ( old_name , alias . first ) = = 0 ;
} ) ;
if ( alias = = c_option_aliases . end ( ) )
return nullptr ;
2021-03-11 20:04:12 -06:00
2020-10-06 12:09:27 -05:00
return & alias - > second ;
}
} ;
const OptionAliases Aliases : : c_option_aliases
{
{ " Accounts to include " , { nullptr , " Accounts " } } ,
{ " Exclude transactions between selected accounts? " ,
{ nullptr , " Exclude transactions between selected accounts " } } ,
2022-12-23 14:43:54 -06:00
{ " Filter Accounts " , { nullptr , " Filter By… " } } ,
2020-10-06 12:09:27 -05:00
{ " Flatten list to depth limit? " ,
{ nullptr , " Flatten list to depth limit " } } ,
{ " From " , { nullptr , " Start Date " } } ,
{ " Report Accounts " , { nullptr , " Accounts " } } ,
{ " Report Currency " , { nullptr , " Report's currency " } } ,
{ " Show Account Code? " , { nullptr , " Show Account Code " } } ,
{ " Show Full Account Name? " , { nullptr , " Show Full Account Name " } } ,
{ " Show Multi-currency Totals? " ,
{ nullptr , " Show Multi-currency Totals " } } ,
{ " Show zero balance items? " , { nullptr , " Show zero balance items " } } ,
{ " Sign Reverses? " , { nullptr , " Sign Reverses " } } ,
{ " To " , { nullptr , " End Date " } } ,
{ " Charge Type " , { nullptr , " Action " } } , // easy-invoice.scm, renamed June 2018
2021-07-13 11:46:07 -05:00
// the following 4 options in income-gst-statement.scm renamed Dec 2018
2020-10-06 12:09:27 -05:00
{ " Individual income columns " , { nullptr , " Individual sales columns " } } ,
{ " Individual expense columns " ,
{ nullptr , " Individual purchases columns " } } ,
{ " Remittance amount " , { nullptr , " Gross Balance " } } ,
{ " Net Income " , { nullptr , " Net Balance " } } ,
2021-07-13 11:46:07 -05:00
// transaction.scm:
2020-10-06 12:09:27 -05:00
{ " Use Full Account Name? " , { nullptr , " Use Full Account Name " } } ,
{ " Use Full Other Account Name? " ,
{ nullptr , " Use Full Other Account Name " } } ,
{ " Void Transactions? " , { " Filter " , " Void Transactions " } } ,
{ " Void Transactions " , { " Filter " , " Void Transactions " } } ,
{ " Account Substring " , { " Filter " , " Account Name Filter " } } ,
{ " Enable links " , { nullptr , " Enable Links " } } ,
2021-07-13 11:46:07 -05:00
// trep-engine: moved currency options to own tab
{ " Common Currency " , { " Currency " , " Common Currency " } } ,
{ " Show original currency amount " ,
{ " Currency " , " Show original currency amount " } } ,
{ " Report's currency " , { " Currency " , " Report's currency " } } ,
{ " Reconcile Status " , { nullptr , " Reconciled Status " } } ,
// new-owner-report.scm, renamed Oct 2020 to differentiate with
// Document Links:
{ " Links " , { nullptr , " Transaction Links " } } ,
// invoice.scm, renamed November 2018
2020-10-06 12:09:27 -05:00
{ " Individual Taxes " , { nullptr , " Use Detailed Tax Summary " } } ,
2021-08-04 19:13:23 -05:00
{ " Show Accounts until level " , { nullptr , " Levels of Subaccounts " } } ,
{ " Invoice number " , { nullptr , " Invoice Number " } } ,
{ " Report title " , { nullptr , " Report Title " } } ,
{ " Extra notes " , { nullptr , " Extra Notes " } } ,
2021-07-13 11:46:07 -05:00
// income-gst-statement.scm
{ " default format " , { nullptr , " Default Format " } } ,
{ " Report format " , { nullptr , " Report Format " } } ,
2022-12-24 08:14:00 -06:00
// ... replaced to …, Dec 2022
{ " Filter By... " , { nullptr , " Filter By… " } } ,
{ " Specify date to filter by... " , { nullptr , " Specify date to filter by… " } } ,
2020-10-06 12:09:27 -05:00
} ;
2019-08-06 17:03:48 -05:00
2020-03-17 14:19:26 -05:00
static bool
operator = = ( const std : : string & str , const char * cstr )
{
return strcmp ( str . c_str ( ) , cstr ) = = 0 ;
}
2019-08-06 17:03:48 -05:00
2020-03-17 14:24:20 -05:00
void
GncOptionSection : : foreach_option ( std : : function < void ( GncOption & ) > func )
{
std : : for_each ( m_options . begin ( ) , m_options . end ( ) , func ) ;
}
2020-03-24 13:06:57 -05:00
void
GncOptionSection : : foreach_option ( std : : function < void ( const GncOption & ) > func ) const
{
std : : for_each ( m_options . begin ( ) , m_options . end ( ) , func ) ;
}
2020-03-17 14:24:20 -05:00
void
GncOptionSection : : add_option ( GncOption & & option )
{
2021-08-18 16:37:20 -05:00
m_options . push_back ( std : : move ( option ) ) ;
if ( ! std : : is_sorted ( m_options . begin ( ) , m_options . end ( ) ) )
std : : sort ( m_options . begin ( ) , m_options . end ( ) ) ;
2020-03-17 14:24:20 -05:00
}
void
GncOptionSection : : remove_option ( const char * name )
{
m_options . erase ( std : : remove_if ( m_options . begin ( ) , m_options . end ( ) ,
[ name ] ( const auto & option ) - > bool
{
return option . get_name ( ) = = name ;
} ) ) ;
}
const GncOption *
GncOptionSection : : find_option ( const char * name ) const
{
auto option = std : : find_if ( m_options . begin ( ) , m_options . end ( ) ,
[ name ] ( auto & option ) - > bool {
return option . get_name ( ) = = name ;
} ) ;
2020-10-06 12:09:27 -05:00
if ( option ! = m_options . end ( ) )
return & * option ;
auto alias = Aliases : : find_alias ( name ) ;
if ( ! alias | | alias - > first ) // No alias or the alias
return nullptr ; // is in a different section.
return find_option ( alias - > second ) ;
2020-03-17 14:24:20 -05:00
}
GncOptionDB : : GncOptionDB ( ) : m_default_section { } { }
GncOptionDB : : GncOptionDB ( QofBook * book ) : GncOptionDB ( ) { }
2019-08-06 17:03:48 -05:00
void
2020-03-17 14:24:20 -05:00
GncOptionDB : : register_option ( const char * sectname , GncOption & & option )
2019-08-06 17:03:48 -05:00
{
2020-03-17 14:24:20 -05:00
auto section = find_section ( sectname ) ;
2019-08-06 17:03:48 -05:00
2020-03-17 14:24:20 -05:00
if ( section )
2019-08-06 17:03:48 -05:00
{
2020-03-17 14:24:20 -05:00
section - > add_option ( std : : move ( option ) ) ;
2019-09-29 12:06:00 -05:00
return ;
2019-08-06 17:03:48 -05:00
}
2019-09-29 12:06:00 -05:00
2021-08-18 16:37:20 -05:00
m_sections . push_back ( std : : make_shared < GncOptionSection > ( sectname ) ) ;
2020-03-17 14:24:20 -05:00
m_sections . back ( ) - > add_option ( std : : move ( option ) ) ;
2021-08-18 16:37:20 -05:00
if ( ! std : : is_sorted ( m_sections . begin ( ) , m_sections . end ( ) ) )
std : : sort ( m_sections . begin ( ) , m_sections . end ( ) ) ;
2019-08-06 17:03:48 -05:00
}
2021-01-04 19:08:03 -06:00
void
GncOptionDB : : register_option ( const char * sectname , GncOption * option )
{
register_option ( sectname , std : : move ( * option ) ) ;
delete option ;
}
2019-08-06 17:03:48 -05:00
void
2020-03-17 14:24:20 -05:00
GncOptionDB : : unregister_option ( const char * sectname , const char * name )
2019-08-06 17:03:48 -05:00
{
2020-03-17 14:24:20 -05:00
auto section = find_section ( sectname ) ;
if ( section )
section - > remove_option ( name ) ;
2019-08-06 17:03:48 -05:00
}
void
2020-03-17 14:24:20 -05:00
GncOptionDB : : set_default_section ( const char * sectname )
2019-08-06 17:03:48 -05:00
{
2020-03-17 14:24:20 -05:00
m_default_section = find_section ( sectname ) ;
2019-08-06 17:03:48 -05:00
}
2019-09-29 12:06:00 -05:00
const GncOptionSection * const
GncOptionDB : : get_default_section ( ) const noexcept
{
2020-03-17 14:24:20 -05:00
return m_default_section ;
2019-09-29 12:06:00 -05:00
}
2019-09-29 12:28:04 -05:00
2020-03-17 14:24:20 -05:00
const GncOptionSection *
GncOptionDB : : find_section ( const std : : string & section ) const
2019-08-06 17:03:48 -05:00
{
2020-03-17 14:24:20 -05:00
auto db_section = std : : find_if ( m_sections . begin ( ) , m_sections . end ( ) ,
[ & section ] ( auto & sect ) - > bool
{
return section = = sect - > get_name ( ) ;
} ) ;
return db_section = = m_sections . end ( ) ? nullptr : db_section - > get ( ) ;
2019-09-29 12:06:00 -05:00
}
2020-03-17 14:24:20 -05:00
const GncOption *
GncOptionDB : : find_option ( const std : : string & section , const char * name ) const
2019-09-29 12:06:00 -05:00
{
2019-11-22 17:45:42 -06:00
auto db_section = const_cast < GncOptionDB * > ( this ) - > find_section ( section ) ;
2020-10-06 12:09:27 -05:00
const GncOption * option = nullptr ;
if ( db_section )
option = db_section - > find_option ( name ) ;
if ( option )
return option ;
auto alias = Aliases : : find_alias ( name ) ;
/* Only try again if alias.first isn't
* nullptr . GncOptionSection : : find_option already checked if the alias
* should have been in the same section .
*/
2021-07-13 11:46:48 -05:00
if ( alias & & alias - > first & & section ! = alias - > first )
2020-10-06 12:09:27 -05:00
return find_option ( alias - > first , alias - > second ) ;
2020-10-06 12:14:10 -05:00
return nullptr ;
2019-09-29 12:06:00 -05:00
}
2019-08-06 17:03:48 -05:00
std : : string
2019-09-29 12:06:00 -05:00
GncOptionDB : : lookup_string_option ( const char * section , const char * name )
2019-08-06 17:03:48 -05:00
{
2019-09-29 12:06:00 -05:00
static const std : : string empty_string { } ;
auto db_opt = find_option ( section , name ) ;
if ( ! db_opt )
2019-08-06 17:03:48 -05:00
return empty_string ;
2020-03-17 14:24:20 -05:00
return db_opt - > get_value < std : : string > ( ) ;
2019-08-06 17:03:48 -05:00
}
2019-10-01 18:03:15 -05:00
void
GncOptionDB : : make_internal ( const char * section , const char * name )
{
2020-01-27 15:40:39 -06:00
2019-10-01 18:03:15 -05:00
auto db_opt = find_option ( section , name ) ;
if ( db_opt )
2020-03-17 14:24:20 -05:00
db_opt - > make_internal ( ) ;
2019-10-01 18:03:15 -05:00
}
2019-12-14 17:43:24 -06:00
static inline bool constexpr
is_eol ( char c )
{
return c = = ' \n ' ;
}
static inline bool constexpr
is_whitespace ( char c )
{
return c = = ' ' | | c = = ' \n ' | | c = = ' \t ' ;
}
static inline bool constexpr
is_begin_paren ( char c )
{
return c = = ' ( ' ;
}
static inline bool constexpr
is_end_paren ( char c )
{
return c = = ' ) ' ;
}
static inline bool constexpr
is_double_quote ( char c )
{
return c = = ' " ' ;
}
static inline bool constexpr
is_single_quote ( char c )
{
return c = = ' \' ' ;
}
static inline bool constexpr
is_semicolon ( char c )
{
return c = = ' ; ' ;
}
static inline bool constexpr
is_delim ( char c )
{
return is_begin_paren ( c ) | | is_end_paren ( c ) | | is_whitespace ( c ) | |
is_single_quote ( c ) | | is_double_quote ( c ) | | is_semicolon ( c ) ;
}
2019-11-22 17:45:42 -06:00
std : : ostream &
2019-12-05 20:00:07 -06:00
GncOptionDB : : save_option_key_value ( std : : ostream & oss ,
2020-01-20 13:37:21 -06:00
const std : : string & section ,
const std : : string & name ) const noexcept
2019-11-22 17:45:42 -06:00
{
2020-03-17 14:24:20 -05:00
auto db_opt = find_option ( section , name . c_str ( ) ) ;
if ( ! db_opt | | ! db_opt - > is_changed ( ) )
2019-11-22 17:45:42 -06:00
return oss ;
2020-01-20 13:37:21 -06:00
oss < < section . substr ( 0 , classifier_size_max ) < < " : " < <
2020-03-17 14:24:20 -05:00
name . substr ( 0 , classifier_size_max ) < < " = " < < * db_opt < < " ; " ;
2019-11-22 17:45:42 -06:00
return oss ;
}
2019-12-05 20:00:07 -06:00
std : : istream &
GncOptionDB : : load_option_key_value ( std : : istream & iss )
2019-08-06 17:03:48 -05:00
{
2019-12-05 20:00:07 -06:00
char section [ classifier_size_max ] , name [ classifier_size_max ] ;
iss . getline ( section , classifier_size_max , ' : ' ) ;
iss . getline ( name , classifier_size_max , ' = ' ) ;
if ( ! iss )
throw std : : invalid_argument ( " Section or name delimiter not found or values too long " ) ;
auto option = find_option ( section , name ) ;
if ( ! option )
iss . ignore ( stream_max , ' ; ' ) ;
else
{
std : : string value ;
std : : getline ( iss , value , ' ; ' ) ;
std : : istringstream item_iss { value } ;
2020-03-17 14:24:20 -05:00
item_iss > > * option ;
2019-12-05 20:00:07 -06:00
}
return iss ;
2019-08-06 17:03:48 -05:00
}
2019-08-06 17:29:58 -05:00
2020-01-20 13:37:21 -06:00
std : : ostream &
GncOptionDB : : save_to_key_value ( std : : ostream & oss ) const noexcept
{
2020-03-17 14:24:20 -05:00
foreach_section (
[ & oss ] ( const GncOptionSectionPtr & section )
2020-01-20 13:37:21 -06:00
{
2020-03-17 14:24:20 -05:00
oss < < " [Options] \n " ;
section - > foreach_option (
[ & oss , & section ] ( auto & option )
{
if ( option . is_changed ( ) )
oss < < section - > get_name ( ) . substr ( 0 , classifier_size_max ) < <
' : ' < < option . get_name ( ) . substr ( 0 , classifier_size_max ) < <
' = ' < < option < < ' \n ' ;
} ) ;
} ) ;
2020-01-20 13:37:21 -06:00
return oss ;
}
std : : istream &
GncOptionDB : : load_from_key_value ( std : : istream & iss )
{
if ( iss . peek ( ) = = ' [ ' )
{
char buf [ classifier_size_max ] ;
iss . getline ( buf , classifier_size_max ) ;
if ( strcmp ( buf , " [Options] " ) ! = 0 ) // safe
throw std : : runtime_error ( " Wrong secion header for options. " ) ;
}
// Otherwise assume we were sent here correctly:
while ( iss . peek ( ) ! = ' [ ' ) //Indicates the start of the next file section
{
load_option_key_value ( iss ) ;
}
return iss ;
}
2021-08-12 16:29:56 -05:00
size_t
GncOptionDB : : register_callback ( GncOptionDBChangeCallback cb , void * data )
{
constexpr std : : hash < GncOptionDBChangeCallback > cb_hash ;
auto id { cb_hash ( cb ) } ;
if ( std : : find_if ( m_callbacks . begin ( ) , m_callbacks . end ( ) ,
[ id ] ( auto & cb ) - > bool { return cb . m_id = = id ; } ) = = m_callbacks . end ( ) )
m_callbacks . emplace_back ( id , cb , data ) ;
return id ;
}
void
GncOptionDB : : unregister_callback ( size_t id )
{
std : : remove_if ( m_callbacks . begin ( ) , m_callbacks . end ( ) ,
[ id ] ( auto & cb ) - > bool { return cb . m_id = = id ; } ) ;
}
void
GncOptionDB : : run_callbacks ( )
{
std : : for_each ( m_callbacks . begin ( ) , m_callbacks . end ( ) ,
[ ] ( auto & cb ) - > void { cb . m_func ( cb . m_data ) ; } ) ;
}
2020-04-08 14:20:12 -05:00
static inline void
counter_option_path ( const GncOption & option , GSList * list , std : : string & name )
{
constexpr const char * counters { " counters " } ;
2022-04-07 04:33:11 -05:00
constexpr const char * formats { " counter_formats " } ;
2020-04-08 14:20:12 -05:00
auto key = option . get_key ( ) ;
name = key . substr ( 0 , key . size ( ) - 1 ) ;
list - > next - > data = ( void * ) name . c_str ( ) ;
if ( option . get_name ( ) . rfind ( " format " )
! = std : : string : : npos )
list - > data = ( void * ) formats ;
else
list - > data = ( void * ) counters ;
}
static inline void
option_path ( const GncOption & option , GSList * list )
{
list - > next - > data = ( void * ) option . get_name ( ) . c_str ( ) ;
list - > data = ( void * ) option . get_section ( ) . c_str ( ) ;
}
static inline KvpValue *
kvp_value_from_bool_option ( const GncOption & option )
{
auto val { option . template get_value < bool > ( ) } ;
// ~KvpValue will g_free the value.
return new KvpValue ( val ? g_strdup ( " t " ) : g_strdup ( " f " ) ) ;
}
static bool
2020-04-04 19:47:26 -05:00
is_qofinstance_ui_type ( GncOptionUIType type )
{
switch ( type )
{
2021-01-04 19:13:53 -06:00
case GncOptionUIType : : ACCOUNT_SEL :
case GncOptionUIType : : BUDGET :
case GncOptionUIType : : OWNER :
case GncOptionUIType : : CUSTOMER :
case GncOptionUIType : : VENDOR :
case GncOptionUIType : : EMPLOYEE :
case GncOptionUIType : : INVOICE :
case GncOptionUIType : : TAX_TABLE :
case GncOptionUIType : : QUERY :
2020-04-04 19:47:26 -05:00
return true ;
default :
return false ;
}
}
2020-04-08 14:20:12 -05:00
static inline KvpValue *
kvp_value_from_qof_instance_option ( const GncOption & option )
{
const QofInstance * inst { QOF_INSTANCE ( option . template get_value < const QofInstance * > ( ) ) } ;
auto guid = guid_copy ( qof_instance_get_guid ( inst ) ) ;
return new KvpValue ( guid ) ;
}
2020-01-20 13:37:21 -06:00
void
GncOptionDB : : save_to_kvp ( QofBook * book , bool clear_options ) const noexcept
{
if ( clear_options )
qof_book_options_delete ( book , nullptr ) ;
2020-03-17 14:24:20 -05:00
const_cast < GncOptionDB * > ( this ) - > foreach_section (
2020-04-08 14:20:12 -05:00
[ book ] ( GncOptionSectionPtr & section )
2020-03-17 14:24:20 -05:00
{
section - > foreach_option (
2020-04-08 14:20:12 -05:00
[ book , & section ] ( auto & option ) {
if ( option . is_changed ( ) )
2020-03-17 14:24:20 -05:00
{
2020-04-08 14:20:12 -05:00
/* We need the string name out here so that it stays in
* scope long enough to pass its c_str to
* gnc_book_set_option . */
std : : string name ;
/* qof_book_set_option wants a GSList path. Let's avoid
* allocating and make one here . */
GSList list_tail { } , list_head { nullptr , & list_tail } ;
if ( strcmp ( section - > get_name ( ) . c_str ( ) , " Counters " ) = = 0 )
counter_option_path ( option , & list_head , name ) ;
else
option_path ( option , & list_head ) ;
2020-03-17 14:24:20 -05:00
auto type { option . get_ui_type ( ) } ;
2020-04-08 14:20:12 -05:00
KvpValue * kvp { } ;
2020-03-17 14:24:20 -05:00
if ( type = = GncOptionUIType : : BOOLEAN )
2020-04-08 14:20:12 -05:00
kvp = kvp_value_from_bool_option ( option ) ;
2020-04-04 19:47:26 -05:00
else if ( is_qofinstance_ui_type ( type ) )
2020-04-08 14:20:12 -05:00
kvp = kvp_value_from_qof_instance_option ( option ) ;
2020-03-17 14:24:20 -05:00
else if ( type = = GncOptionUIType : : NUMBER_RANGE )
2020-04-04 19:27:15 -05:00
/* The Gtk control uses a double so that's what we
* have to store . */
2020-04-08 14:20:12 -05:00
kvp = new KvpValue ( option . template get_value < double > ( ) ) ;
2020-03-17 14:24:20 -05:00
else
2020-04-08 14:20:12 -05:00
kvp = new KvpValue { g_strdup ( option . template get_value < std : : string > ( ) . c_str ( ) ) } ;
qof_book_set_option ( book , kvp , & list_head ) ;
2020-03-17 14:24:20 -05:00
}
} ) ;
} ) ;
2020-01-20 13:37:21 -06:00
}
2020-04-08 14:20:12 -05:00
static inline void
fill_option_from_string_kvp ( GncOption & option , KvpValue * kvp )
{
auto str { kvp - > get < const char * > ( ) } ;
if ( option . get_ui_type ( ) = = GncOptionUIType : : BOOLEAN )
option . set_value ( * str = = ' t ' ? true : false ) ;
else
option . set_value ( std : : string { str } ) ;
}
static inline void
fill_option_from_guid_kvp ( GncOption & option , KvpValue * kvp )
{
auto guid { kvp - > get < GncGUID * > ( ) } ;
option . set_value (
( const QofInstance * ) qof_instance_from_guid ( guid , option . get_ui_type ( ) ) ) ;
}
2020-01-20 13:37:21 -06:00
void
GncOptionDB : : load_from_kvp ( QofBook * book ) noexcept
{
2020-03-17 14:24:20 -05:00
foreach_section (
[ book ] ( GncOptionSectionPtr & section )
2020-01-20 13:37:21 -06:00
{
2020-03-17 14:24:20 -05:00
section - > foreach_option (
2020-03-24 13:06:57 -05:00
[ book , & section ] ( GncOption & option )
2020-01-20 13:37:21 -06:00
{
2020-04-08 14:20:12 -05:00
// Make path list as above.
std : : string name ;
/* qof_book_set_option wants a GSList path. Let's avoid
* allocating and make one here . */
GSList list_tail { } , list_head { nullptr , & list_tail } ;
if ( strcmp ( section - > get_name ( ) . c_str ( ) , " Counters " ) = = 0 )
counter_option_path ( option , & list_head , name ) ;
else
option_path ( option , & list_head ) ;
2020-03-17 14:24:20 -05:00
auto kvp = qof_book_get_option ( book , & list_head ) ;
if ( ! kvp )
return ;
switch ( kvp - > get_type ( ) )
{
2020-04-04 19:27:15 -05:00
case KvpValue : : Type : : DOUBLE :
option . set_value ( kvp - > get < double > ( ) ) ;
break ;
2020-03-17 14:24:20 -05:00
case KvpValue : : Type : : INT64 :
option . set_value ( kvp - > get < int64_t > ( ) ) ;
break ;
case KvpValue : : Type : : STRING :
2020-04-08 14:20:12 -05:00
fill_option_from_string_kvp ( option , kvp ) ;
2020-03-17 14:24:20 -05:00
break ;
case KvpValue : : Type : : GUID :
2020-04-08 14:20:12 -05:00
fill_option_from_guid_kvp ( option , kvp ) ;
break ;
2020-03-17 14:24:20 -05:00
default :
return ;
break ;
}
} ) ;
} ) ;
2020-01-20 13:37:21 -06:00
}
2019-08-06 17:29:58 -05:00
void
2020-04-04 16:16:22 -05:00
gnc_register_string_option ( GncOptionDB * db , const char * section ,
2019-08-06 17:29:58 -05:00
const char * name , const char * key ,
const char * doc_string , std : : string value )
{
2019-09-29 12:11:48 -05:00
GncOption option { section , name , key , doc_string , value ,
GncOptionUIType : : STRING } ;
2019-08-06 17:29:58 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
void
2020-04-04 16:16:22 -05:00
gnc_register_text_option ( GncOptionDB * db , const char * section , const char * name ,
2019-08-06 17:29:58 -05:00
const char * key , const char * doc_string ,
std : : string value )
{
2019-09-29 12:11:48 -05:00
GncOption option { section , name , key , doc_string , value ,
GncOptionUIType : : TEXT } ;
db - > register_option ( section , std : : move ( option ) ) ;
2019-08-06 17:29:58 -05:00
}
2019-10-01 18:03:15 -05:00
void
2020-04-04 16:16:22 -05:00
gnc_register_font_option ( GncOptionDB * db , const char * section ,
2019-10-01 18:03:15 -05:00
const char * name , const char * key ,
const char * doc_string , std : : string value )
{
GncOption option { section , name , key , doc_string , value ,
GncOptionUIType : : FONT } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
2019-08-06 17:29:58 -05:00
void
2020-04-04 16:16:22 -05:00
gnc_register_budget_option ( GncOptionDB * db , const char * section ,
2019-08-06 17:29:58 -05:00
const char * name , const char * key ,
const char * doc_string , GncBudget * value )
{
2021-12-30 14:21:56 -06:00
GncOption option { GncOptionQofInstanceValue { section , name , key , doc_string ,
( const QofInstance * ) value ,
GncOptionUIType : : BUDGET } } ;
2019-08-06 17:29:58 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
2019-10-01 18:03:15 -05:00
void
2020-04-04 16:16:22 -05:00
gnc_register_color_option ( GncOptionDB * db , const char * section ,
2019-10-01 18:03:15 -05:00
const char * name , const char * key ,
const char * doc_string , std : : string value )
{
GncOption option { section , name , key , doc_string , value ,
2019-11-17 13:15:56 -06:00
GncOptionUIType : : COLOR } ;
2019-10-01 18:03:15 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
2019-08-06 17:29:58 -05:00
void
2020-04-04 16:16:22 -05:00
gnc_register_commodity_option ( GncOptionDB * db , const char * section ,
2019-08-06 17:29:58 -05:00
const char * name , const char * key ,
const char * doc_string , gnc_commodity * value )
{
2022-01-03 16:47:18 -06:00
GncOption option { GncOptionCommodityValue { section , name , key , doc_string ,
value ,
2021-12-30 14:21:56 -06:00
GncOptionUIType : : COMMODITY } } ;
2019-08-06 17:29:58 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
2022-08-05 18:01:31 -05:00
void
gnc_register_commodity_option ( GncOptionDB * db , const char * section ,
const char * name , const char * key ,
const char * doc_string , const char * value )
{
gnc_commodity * commodity { } ;
const auto book { qof_session_get_book ( gnc_get_current_session ( ) ) } ;
const auto commodity_table { gnc_commodity_table_get_table ( book ) } ;
const auto namespaces { gnc_commodity_table_get_namespaces ( commodity_table ) } ;
for ( auto node = namespaces ; node & & commodity = = nullptr ;
node = g_list_next ( node ) )
{
commodity = gnc_commodity_table_lookup ( commodity_table ,
( const char * ) ( node - > data ) ,
value ) ;
if ( commodity )
break ;
}
GncOption option { GncOptionCommodityValue { section , name , key , doc_string ,
commodity ,
GncOptionUIType : : COMMODITY } } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
2019-10-01 18:03:15 -05:00
void
2020-04-04 16:16:22 -05:00
gnc_register_simple_boolean_option ( GncOptionDB * db ,
2019-10-01 18:03:15 -05:00
const char * section , const char * name ,
const char * key , const char * doc_string ,
bool value )
{
GncOption option { section , name , key , doc_string , value ,
2020-04-04 16:42:59 -05:00
GncOptionUIType : : BOOLEAN } ;
2019-10-01 18:03:15 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
void
2020-04-04 16:16:22 -05:00
gnc_register_pixmap_option ( GncOptionDB * db , const char * section ,
2019-10-01 18:03:15 -05:00
const char * name , const char * key ,
const char * doc_string , std : : string value )
{
GncOption option { section , name , key , doc_string , value ,
GncOptionUIType : : PIXMAP } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
void
2020-04-04 16:16:22 -05:00
gnc_register_account_list_option ( GncOptionDB * db , const char * section ,
2019-10-01 18:03:15 -05:00
const char * name , const char * key ,
const char * doc_string ,
2019-11-17 13:15:56 -06:00
const GncOptionAccountList & value )
2019-10-01 18:03:15 -05:00
{
2021-07-31 19:43:48 -05:00
GncOption option { GncOptionAccountListValue { section , name , key , doc_string ,
2019-11-17 13:15:56 -06:00
GncOptionUIType : : ACCOUNT_LIST , value } } ;
2019-10-01 18:03:15 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
void
2020-04-04 16:16:22 -05:00
gnc_register_account_list_limited_option ( GncOptionDB * db ,
2019-11-17 13:15:56 -06:00
const char * section , const char * name ,
const char * key ,
const char * doc_string ,
const GncOptionAccountList & value ,
GncOptionAccountTypeList & & allowed )
2019-10-01 18:03:15 -05:00
{
2019-11-17 13:15:56 -06:00
try
{
2021-07-31 19:43:48 -05:00
GncOption option { GncOptionAccountListValue { section , name , key , doc_string ,
2019-11-17 13:15:56 -06:00
GncOptionUIType : : ACCOUNT_LIST , value , std : : move ( allowed ) } } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
catch ( const std : : invalid_argument & err )
{
2022-08-18 13:19:04 -05:00
PWARN ( " Account List Limited Option, value failed validation, option not registered. " ) ;
2019-11-17 13:15:56 -06:00
}
}
using AccountPair = std : : pair < GncOptionAccountList & ,
const GncOptionAccountTypeList & > ;
static void
find_children ( Account * account , void * data )
{
auto datapair =
( AccountPair * ) data ;
GncOptionAccountList & list = datapair - > first ;
const GncOptionAccountTypeList & types = datapair - > second ;
if ( std : : find ( types . begin ( ) , types . end ( ) ,
xaccAccountGetType ( account ) ) ! = types . end ( ) )
2022-03-12 19:58:23 -06:00
list . push_back ( * qof_entity_get_guid ( account ) ) ;
2019-11-17 13:15:56 -06:00
}
GncOptionAccountList
gnc_account_list_from_types ( QofBook * book ,
const GncOptionAccountTypeList & types )
{
GncOptionAccountList list ;
AccountPair funcdata { list , types } ;
Account * base_acct = gnc_book_get_root_account ( book ) ;
gnc_account_foreach_descendant ( base_acct , ( AccountCb ) find_children ,
& funcdata ) ;
return list ;
2019-10-01 18:03:15 -05:00
}
2019-11-17 13:15:56 -06:00
2019-10-01 18:03:15 -05:00
void
2020-04-04 16:16:22 -05:00
gnc_register_account_sel_limited_option ( GncOptionDB * db ,
2019-10-01 18:03:15 -05:00
const char * section , const char * name ,
const char * key , const char * doc_string ,
2021-07-31 19:43:48 -05:00
const Account * value ,
2019-11-17 13:15:56 -06:00
GncOptionAccountTypeList & & allowed )
2019-10-01 18:03:15 -05:00
{
2019-11-17 13:15:56 -06:00
try
{
2021-07-31 19:43:48 -05:00
GncOption option { GncOptionAccountSelValue { section , name , key , doc_string ,
2019-11-17 13:15:56 -06:00
GncOptionUIType : : ACCOUNT_SEL , value , std : : move ( allowed ) } } ;
2019-10-01 18:03:15 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
2019-11-17 13:15:56 -06:00
}
catch ( const std : : invalid_argument & err )
{
2022-08-18 13:19:04 -05:00
PWARN ( " Account Sel Limited Option, value failed validation, option not registerd. " ) ;
2019-11-17 13:15:56 -06:00
}
2019-10-01 18:03:15 -05:00
}
void
2020-04-04 16:16:22 -05:00
gnc_register_multichoice_option ( GncOptionDB * db , const char * section ,
2019-10-01 18:03:15 -05:00
const char * name , const char * key ,
2021-02-25 12:34:43 -06:00
const char * doc_string , const char * default_val ,
2020-03-26 18:09:02 -05:00
GncMultichoiceOptionChoices & & choices )
2019-10-01 18:03:15 -05:00
{
2021-02-25 12:34:43 -06:00
std : : string defval { default_val } ;
auto found { std : : find_if ( choices . begin ( ) , choices . end ( ) ,
[ & defval ] ( auto & choice ) - > bool {
return defval = = std : : get < 0 > ( choice ) ;
} ) } ;
if ( found = = choices . end ( ) )
defval = ( choices . empty ( ) ? std : : string { " None " } :
std : : get < 0 > ( choices . at ( 0 ) ) ) ;
2019-10-20 17:13:33 -05:00
GncOption option { GncOptionMultichoiceValue { section , name , key , doc_string ,
2021-02-25 12:34:43 -06:00
defval . c_str ( ) , std : : move ( choices ) } } ;
2019-10-01 18:03:15 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
void
2020-04-04 16:16:22 -05:00
gnc_register_list_option ( GncOptionDB * db , const char * section ,
2019-10-01 18:03:15 -05:00
const char * name , const char * key ,
2019-11-02 13:06:12 -05:00
const char * doc_string , const char * value ,
2020-03-26 18:09:02 -05:00
GncMultichoiceOptionChoices & & list )
2019-10-01 18:03:15 -05:00
{
2019-10-20 17:13:33 -05:00
GncOption option { GncOptionMultichoiceValue { section , name , key , doc_string ,
2019-11-02 13:06:12 -05:00
value , std : : move ( list ) , GncOptionUIType : : LIST } } ;
2019-10-01 18:03:15 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
/* Only balance-forecast.scm, hello-world.scm, and net-charts.scm
2020-01-27 15:40:39 -06:00
* use decimals and fractional steps and they can be worked around .
*/
2020-04-04 16:34:45 -05:00
template < typename ValueType > void
2020-04-04 16:16:22 -05:00
gnc_register_number_range_option ( GncOptionDB * db , const char * section ,
2019-10-01 18:03:15 -05:00
const char * name , const char * key ,
2020-04-04 16:34:45 -05:00
const char * doc_string , ValueType value ,
ValueType min , ValueType max , ValueType step )
2019-10-01 18:03:15 -05:00
{
2020-04-08 14:20:06 -05:00
try
{
GncOption option { GncOptionRangeValue < ValueType > { section , name , key ,
doc_string , value , min ,
max , step } } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
catch ( const std : : invalid_argument & err )
{
2022-08-18 13:19:04 -05:00
PWARN ( " Number Range Option %s, option not registerd. " ,
err . what ( ) ) ;
2020-04-08 14:20:06 -05:00
}
2019-10-01 18:03:15 -05:00
}
void
2020-04-04 16:16:22 -05:00
gnc_register_number_plot_size_option ( GncOptionDB * db ,
2019-10-01 18:03:15 -05:00
const char * section , const char * name ,
const char * key , const char * doc_string ,
int value )
{
2021-02-18 19:38:10 -06:00
// Pixel values don't make much sense so always use percent.
2019-10-01 18:03:15 -05:00
GncOption option { GncOptionRangeValue < int > { section , name , key , doc_string ,
2021-02-18 19:38:10 -06:00
value , 10 , 100 , 1 } } ;
2019-10-01 18:03:15 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
void
2020-04-04 16:16:22 -05:00
gnc_register_query_option ( GncOptionDB * db , const char * section ,
2022-08-06 12:40:04 -05:00
const char * name , const QofQuery * value )
2019-10-01 18:03:15 -05:00
{
2022-08-06 12:40:04 -05:00
GncOption option { section , name , " " , " " , value ,
2021-07-30 15:19:17 -05:00
GncOptionUIType : : INTERNAL } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
void
gnc_register_owner_option ( GncOptionDB * db , const char * section ,
const char * name , const char * key ,
2022-08-05 15:38:12 -05:00
const char * doc_string , const GncOwner * value ,
GncOwnerType type )
2021-07-30 15:19:17 -05:00
{
2022-08-05 15:38:12 -05:00
GncOptionUIType uitype ;
switch ( type )
{
case GNC_OWNER_CUSTOMER :
uitype = GncOptionUIType : : CUSTOMER ;
break ;
case GNC_OWNER_EMPLOYEE :
uitype = GncOptionUIType : : EMPLOYEE ;
break ;
case GNC_OWNER_JOB :
uitype = GncOptionUIType : : JOB ;
break ;
case GNC_OWNER_VENDOR :
uitype = GncOptionUIType : : VENDOR ;
break ;
default :
uitype = GncOptionUIType : : INTERNAL ;
} ;
2021-07-30 15:19:17 -05:00
GncOption option { section , name , key , doc_string , value ,
2022-08-05 15:38:12 -05:00
uitype } ;
2019-10-01 18:03:15 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
void
2020-04-04 16:16:22 -05:00
gnc_register_invoice_option ( GncOptionDB * db , const char * section ,
2020-04-04 16:44:38 -05:00
const char * name , const char * key ,
const char * doc_string , GncInvoice * value )
2019-10-01 18:03:15 -05:00
{
2021-12-30 14:21:56 -06:00
GncOption option { GncOptionQofInstanceValue { section , name , key , doc_string ,
( const QofInstance * ) value ,
GncOptionUIType : : INVOICE } } ;
2019-10-01 18:03:15 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
void
2020-04-04 16:16:22 -05:00
gnc_register_taxtable_option ( GncOptionDB * db , const char * section ,
2019-10-01 18:03:15 -05:00
const char * name , const char * key ,
const char * doc_string , GncTaxTable * value )
{
2021-12-30 14:21:56 -06:00
GncOption option { GncOptionQofInstanceValue { section , name , key , doc_string ,
( const QofInstance * ) value ,
GncOptionUIType : : TAX_TABLE } } ;
2019-10-01 18:03:15 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
void
2020-04-04 16:16:22 -05:00
gnc_register_counter_option ( GncOptionDB * db , const char * section ,
2019-10-01 18:03:15 -05:00
const char * name , const char * key ,
2020-04-04 16:34:45 -05:00
const char * doc_string , double value )
2019-10-01 18:03:15 -05:00
{
2020-04-04 16:34:45 -05:00
GncOption option { GncOptionRangeValue < double > { section , name , key , doc_string ,
value , 0.0 , 999999999.0 , 1.0 } } ;
2019-10-01 18:03:15 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
void
2020-04-04 16:16:22 -05:00
gnc_register_counter_format_option ( GncOptionDB * db ,
2019-10-01 18:03:15 -05:00
const char * section , const char * name ,
const char * key , const char * doc_string ,
std : : string value )
{
GncOption option { section , name , key , doc_string , value ,
GncOptionUIType : : STRING } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
void
2020-04-04 16:16:22 -05:00
gnc_register_dateformat_option ( GncOptionDB * db , const char * section ,
2019-10-01 18:03:15 -05:00
const char * name , const char * key ,
const char * doc_string , std : : string value )
{
GncOption option { section , name , key , doc_string , value ,
GncOptionUIType : : DATE_FORMAT } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
2019-08-06 17:29:58 -05:00
void
2020-04-04 16:16:22 -05:00
gnc_register_currency_option ( GncOptionDB * db , const char * section ,
2019-08-06 17:29:58 -05:00
const char * name , const char * key ,
const char * doc_string , gnc_commodity * value )
{
2022-01-03 16:47:18 -06:00
GncOption option { GncOptionCommodityValue {
2022-08-05 18:01:31 -05:00
section , name , key , doc_string , value , GncOptionUIType : : CURRENCY
} } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
void
gnc_register_currency_option ( GncOptionDB * db , const char * section ,
const char * name , const char * key ,
const char * doc_string , const char * value )
{
const auto book { qof_session_get_book ( gnc_get_current_session ( ) ) } ;
const auto commodity_table { gnc_commodity_table_get_table ( book ) } ;
const auto commodity = gnc_commodity_table_lookup ( commodity_table ,
" CURRENCY " ,
value ) ;
GncOption option { GncOptionCommodityValue {
section , name , key , doc_string , commodity , GncOptionUIType : : CURRENCY
2019-08-06 17:29:58 -05:00
} } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
2019-10-29 18:34:44 -05:00
void
2020-04-04 16:16:22 -05:00
gnc_register_date_option ( GncOptionDB * db , const char * section ,
2020-03-05 20:06:46 -06:00
const char * name , const char * key ,
const char * doc_string , time64 time ,
RelativeDateUI ui )
2019-10-29 18:34:44 -05:00
{
2020-03-05 20:06:46 -06:00
auto ui_type = ui = = RelativeDateUI : : BOTH ? GncOptionUIType : : DATE_BOTH :
ui = = RelativeDateUI : : RELATIVE ? GncOptionUIType : : DATE_RELATIVE :
GncOptionUIType : : DATE_ABSOLUTE ;
GncOption option { GncOptionDateValue ( section , name , key , doc_string ,
ui_type , time ) } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
void
2020-04-04 16:16:22 -05:00
gnc_register_date_option ( GncOptionDB * db , const char * section ,
2020-03-05 20:06:46 -06:00
const char * name , const char * key ,
const char * doc_string , RelativeDatePeriod period ,
RelativeDateUI ui )
{
auto ui_type = ui = = RelativeDateUI : : BOTH ? GncOptionUIType : : DATE_BOTH :
ui = = RelativeDateUI : : RELATIVE ? GncOptionUIType : : DATE_RELATIVE :
GncOptionUIType : : DATE_ABSOLUTE ;
2020-02-18 16:23:59 -06:00
GncOption option { GncOptionDateValue ( section , name , key , doc_string ,
ui_type , period ) } ;
2019-10-29 18:34:44 -05:00
db - > register_option ( section , std : : move ( option ) ) ;
}
2020-03-05 20:06:46 -06:00
void
2020-04-04 16:16:22 -05:00
gnc_register_date_option ( GncOptionDB * db ,
2020-03-05 20:06:46 -06:00
const char * section , const char * name ,
const char * key , const char * doc_string ,
RelativeDatePeriodVec & period_set ,
bool both )
{
2022-07-19 13:11:37 -05:00
auto is_absolute = period_set . size ( ) = = 1 & &
period_set . front ( ) = = RelativeDatePeriod : : ABSOLUTE ;
2020-03-05 20:06:46 -06:00
auto ui_type = both ? GncOptionUIType : : DATE_BOTH :
2022-07-19 13:11:37 -05:00
is_absolute ? GncOptionUIType : : DATE_ABSOLUTE : GncOptionUIType : : DATE_RELATIVE ;
2020-03-05 20:06:46 -06:00
GncOption option { GncOptionDateValue ( section , name , key , doc_string ,
ui_type , period_set ) } ;
2022-07-19 13:11:37 -05:00
if ( is_absolute )
option . set_default_value ( gnc_time ( nullptr ) ) ;
2020-03-05 20:06:46 -06:00
db - > register_option ( section , std : : move ( option ) ) ;
}
static const RelativeDatePeriodVec begin_dates
{
RelativeDatePeriod : : TODAY ,
RelativeDatePeriod : : START_THIS_MONTH ,
RelativeDatePeriod : : START_PREV_MONTH ,
RelativeDatePeriod : : START_CURRENT_QUARTER ,
RelativeDatePeriod : : START_PREV_QUARTER ,
RelativeDatePeriod : : START_CAL_YEAR ,
RelativeDatePeriod : : START_PREV_YEAR ,
RelativeDatePeriod : : START_ACCOUNTING_PERIOD
} ;
void
2020-04-04 16:16:22 -05:00
gnc_register_start_date_option ( GncOptionDB * db , const char * section ,
2020-03-05 20:06:46 -06:00
const char * name , const char * key ,
const char * doc_string , bool both )
{
auto ui_type = both ? GncOptionUIType : : DATE_BOTH :
GncOptionUIType : : DATE_RELATIVE ;
GncOption option { GncOptionDateValue ( section , name , key , doc_string ,
ui_type , begin_dates ) } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
static const RelativeDatePeriodVec end_dates
{
RelativeDatePeriod : : TODAY ,
RelativeDatePeriod : : END_THIS_MONTH ,
RelativeDatePeriod : : END_PREV_MONTH ,
RelativeDatePeriod : : END_CURRENT_QUARTER ,
RelativeDatePeriod : : END_PREV_QUARTER ,
RelativeDatePeriod : : END_CAL_YEAR ,
RelativeDatePeriod : : END_PREV_YEAR ,
RelativeDatePeriod : : END_ACCOUNTING_PERIOD
} ;
void
2020-04-04 16:16:22 -05:00
gnc_register_end_date_option ( GncOptionDB * db , const char * section ,
2020-03-05 20:06:46 -06:00
const char * name , const char * key ,
const char * doc_string , bool both )
{
auto ui_type = both ? GncOptionUIType : : DATE_BOTH :
GncOptionUIType : : DATE_RELATIVE ;
GncOption option { GncOptionDateValue ( section , name , key , doc_string ,
ui_type , end_dates ) } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
2020-03-26 19:43:52 -05:00
2022-03-21 14:46:02 -05:00
void
gnc_register_report_placement_option ( GncOptionDBPtr & db ,
const char * section , const char * name )
{
/* This is a special option with it's own UI file so we have fake values to pass
* to the template creation function .
*/
GncOptionReportPlacementVec value ;
GncOption option { GncOptionValue < GncOptionReportPlacementVec > { section , name ,
" no_key " , " nodoc_string " ,
value , GncOptionUIType : : REPORT_PLACEMENT } } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
2022-07-21 19:11:51 -05:00
void
gnc_register_internal_option ( GncOptionDBPtr & db ,
const char * section , const char * name ,
const std : : string & value )
{
GncOption option {
GncOptionValue < std : : string > { section , name , " " , " " , value ,
GncOptionUIType : : INTERNAL } } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
void
gnc_register_internal_option ( GncOptionDBPtr & db ,
const char * section , const char * name ,
bool value )
{
GncOption option {
GncOptionValue < bool > { section , name , " " , " " , value ,
GncOptionUIType : : INTERNAL } } ;
db - > register_option ( section , std : : move ( option ) ) ;
}
2020-03-26 19:43:52 -05:00
GncOptionDB *
gnc_option_db_new ( void )
{
return new GncOptionDB ;
}
void
gnc_option_db_destroy ( GncOptionDB * odb )
{
2021-08-03 19:05:04 -05:00
PWARN ( " Direct Destroy called on GncOptionDB % " G_GUINT64_FORMAT , ( uint64_t ) odb ) ;
2020-03-26 19:43:52 -05:00
}
GList *
gnc_option_db_commit ( GncOptionDB * odb )
{
GList * errors { } ;
odb - > foreach_section (
[ & errors ] ( GncOptionSectionPtr & section ) {
section - > foreach_option (
[ & errors ] ( GncOption & option ) {
try
{
option . set_option_from_ui_item ( ) ;
}
catch ( const std : : invalid_argument & err )
{
PWARN ( " Option %s:%s failed to set its value %s " ,
option . get_section ( ) . c_str ( ) ,
option . get_name ( ) . c_str ( ) , err . what ( ) ) ;
errors = g_list_prepend ( errors ,
( void * ) option . get_name ( ) . c_str ( ) ) ;
} } ) ;
} ) ;
2021-08-12 16:29:56 -05:00
if ( ! errors )
odb - > run_callbacks ( ) ;
2020-03-26 19:43:52 -05:00
return errors ;
}
void
gnc_option_db_clean ( GncOptionDB * odb )
{
odb - > foreach_section (
[ ] ( GncOptionSectionPtr & section ) {
section - > foreach_option (
[ ] ( GncOption & option ) {
option . set_ui_item_from_option ( ) ;
} ) ;
} ) ;
}
void gnc_option_db_load ( GncOptionDB * odb , QofBook * book )
{
odb - > load_from_kvp ( book ) ;
}
void
gnc_option_db_save ( GncOptionDB * odb , QofBook * book ,
gboolean clear_options )
{
2020-04-04 16:24:43 -05:00
odb - > save_to_kvp ( book , static_cast < bool > ( clear_options ) ) ;
}
2020-04-04 16:33:06 -05:00
void
gnc_option_db_book_options ( GncOptionDB * odb )
{
constexpr const char * business_section { N_ ( " Business " ) } ;
constexpr const char * counter_section { N_ ( " Counters " ) } ;
static const std : : string empty_string { " " } ;
//Accounts Tab
2020-04-04 19:27:15 -05:00
gnc_register_number_range_option < double > ( odb , OPTION_SECTION_ACCOUNTS ,
2020-04-04 16:33:06 -05:00
OPTION_NAME_AUTO_READONLY_DAYS , " a " ,
N_ ( " Choose the number of days after which transactions will be read-only and cannot be edited anymore. This threshold is marked by a red line in the account register windows. If zero, all transactions can be edited and none are read-only. " ) ,
0.0 , 0.0 , 3650.0 , 1.0 ) ;
gnc_register_simple_boolean_option ( odb , OPTION_SECTION_ACCOUNTS ,
OPTION_NAME_NUM_FIELD_SOURCE , " b " ,
N_ ( " Check to have split action field used in registers for 'Num' field in place of transaction number; transaction number shown as 'T-Num' on second line of register. Has corresponding effect on business features, reporting and imports/exports. " ) ,
false ) ;
gnc_register_simple_boolean_option ( odb , OPTION_SECTION_ACCOUNTS ,
OPTION_NAME_TRADING_ACCOUNTS , " a " ,
N_ ( " Check to have trading accounts used for transactions involving more than one currency or commodity. " ) ,
false ) ;
//Budgeting Tab
gnc_register_budget_option ( odb , OPTION_SECTION_BUDGETING ,
OPTION_NAME_DEFAULT_BUDGET , " a " ,
N_ ( " Budget to be used when none has been otherwise specified. " ) ,
nullptr ) ;
//Counters Tab
gnc_register_counter_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Customer number " ) , " gncCustomera " ,
2020-04-04 16:33:06 -05:00
N_ ( " The previous customer number generated. This number will be incremented to generate the next customer number. " ) ,
0.0 ) ;
gnc_register_counter_format_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Customer number format " ) ,
" gncCustomerb " ,
2020-04-04 16:33:06 -05:00
N_ ( " The format string to use for generating customer numbers. This is a printf-style format string. " ) ,
empty_string ) ;
gnc_register_counter_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Employee number " ) , " gncEmployeea " ,
2020-04-04 16:33:06 -05:00
N_ ( " The previous employee number generated. This number will be incremented to generate the next employee number. " ) ,
0.0 ) ;
gnc_register_counter_format_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Employee number format " ) ,
" gncEmployeeb " ,
2020-04-04 16:33:06 -05:00
N_ ( " The format string to use for generating employee numbers. This is a printf-style format string. " ) ,
empty_string ) ;
gnc_register_counter_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Invoice number " ) , " gncInvoicea " ,
2020-04-04 16:33:06 -05:00
N_ ( " The previous invoice number generated. This number will be incremented to generate the next invoice number. " ) ,
0.0 ) ;
gnc_register_counter_format_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Invoice number format " ) ,
" gncInvoiceb " ,
2020-04-04 16:33:06 -05:00
N_ ( " The format string to use for generating invoice numbers. This is a printf-style format string. " ) ,
empty_string ) ;
gnc_register_counter_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Bill number " ) , " gncBilla " ,
2020-04-04 16:33:06 -05:00
N_ ( " The previous bill number generated. This number will be incremented to generate the next bill number. " ) ,
0.0 ) ;
gnc_register_counter_format_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Bill number format " ) , " gncBillb " ,
2020-04-04 16:33:06 -05:00
N_ ( " The format string to use for generating bill numbers. This is a printf-style format string. " ) ,
empty_string ) ;
gnc_register_counter_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Expense voucher number " ) , " gncExpVouchera " ,
2020-04-04 16:33:06 -05:00
N_ ( " The previous expense voucher number generated. This number will be incremented to generate the next voucher number. " ) ,
0.0 ) ;
gnc_register_counter_format_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Expense voucher number format " ) ,
" gncExpVoucherb " ,
2020-04-04 16:33:06 -05:00
N_ ( " The format string to use for generating expense voucher numbers. This is a printf-style format string. " ) ,
empty_string ) ;
gnc_register_counter_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Job number " ) , " gncJoba " ,
2020-04-04 16:33:06 -05:00
N_ ( " The previous job number generated. This number will be incremented to generate the next job number. " ) ,
0.0 ) ;
gnc_register_counter_format_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Job number format " ) , " gncJobb " ,
2020-04-04 16:33:06 -05:00
N_ ( " The format string to use for generating job numbers. This is a printf-style format string. " ) ,
empty_string ) ;
gnc_register_counter_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Order number " ) , " gncOrdera " ,
2020-04-04 16:33:06 -05:00
N_ ( " The previous order number generated. This number will be incremented to generate the next order number. " ) ,
0.0 ) ;
gnc_register_counter_format_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Order number format " ) , " gncOrderb " ,
2020-04-04 16:33:06 -05:00
N_ ( " The format string to use for generating order numbers. This is a printf-style format string. " ) ,
empty_string ) ;
gnc_register_counter_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Vendor number " ) , " gncVendora " ,
2020-04-04 16:33:06 -05:00
N_ ( " The previous vendor number generated. This number will be incremented to generate the next vendor number. " ) ,
0.0 ) ;
gnc_register_counter_format_option ( odb , counter_section ,
2020-04-08 14:20:12 -05:00
N_ ( " Vendor number format " ) , " gncVendorb " ,
2020-04-04 16:33:06 -05:00
N_ ( " The format string to use for generating vendor numbers. This is a printf-style format string. " ) ,
empty_string ) ;
//Business Tab
gnc_register_string_option ( odb , business_section , N_ ( " Company Name " ) , " a " ,
N_ ( " The name of your business. " ) ,
empty_string ) ;
gnc_register_text_option ( odb , business_section , N_ ( " Company Address " ) , " b1 " ,
N_ ( " The address of your business. " ) ,
empty_string ) ;
gnc_register_string_option ( odb , business_section ,
N_ ( " Company Contact Person " ) , " b2 " ,
N_ ( " The contact person to print on invoices. " ) ,
empty_string ) ;
gnc_register_string_option ( odb , business_section ,
N_ ( " Company Phone Number " ) , " c1 " ,
N_ ( " The contact person to print on invoices. " ) ,
empty_string ) ;
gnc_register_string_option ( odb , business_section ,
N_ ( " Company Fax Number " ) , " c2 " ,
N_ ( " The fax number of your business. " ) ,
empty_string ) ;
gnc_register_string_option ( odb , business_section ,
N_ ( " Company Email Address " ) , " c3 " ,
N_ ( " The email address of your business. " ) ,
empty_string ) ;
gnc_register_string_option ( odb , business_section ,
N_ ( " Company Website URL " ) , " c4 " ,
N_ ( " The URL address of your website. " ) ,
empty_string ) ;
gnc_register_string_option ( odb , business_section , N_ ( " Company ID " ) , " c5 " ,
N_ ( " The ID for your company (eg 'Tax-ID: 00-000000). " ) ,
empty_string ) ;
gnc_register_taxtable_option ( odb , business_section ,
N_ ( " Default Customer TaxTable " ) , " e " ,
N_ ( " The default tax table to apply to customers. " ) ,
nullptr ) ;
gnc_register_taxtable_option ( odb , business_section ,
N_ ( " Default Vendor TaxTable " ) , " f " ,
N_ ( " The default tax table to apply to vendors. " ) ,
nullptr ) ;
gnc_register_dateformat_option ( odb , business_section ,
N_ ( " Fancy Date Format " ) , " g " ,
N_ ( " The default date format used for fancy printed dates. " ) ,
empty_string ) ;
//Tax Tab
gnc_register_string_option ( odb , N_ ( " Tax " ) , N_ ( " Tax Number " ) , " a " ,
N_ ( " The electronic tax number of your business " ) ,
empty_string ) ;
}
2020-04-04 16:32:16 -05:00
const char *
2021-02-18 19:36:52 -06:00
gnc_option_db_lookup_string_value ( GncOptionDB * odb , const char * section , const char * name )
2020-04-04 16:32:16 -05:00
{
2021-02-18 19:36:52 -06:00
auto value { odb - > lookup_string_option ( section , name ) } ;
if ( value . empty ( ) )
2021-02-25 12:34:43 -06:00
return nullptr ;
2021-02-18 19:36:52 -06:00
return strdup ( value . c_str ( ) ) ;
2020-04-04 16:32:16 -05:00
}
2020-03-26 19:43:52 -05:00
void
2021-02-18 19:36:52 -06:00
gnc_option_db_set_string_value ( GncOptionDB * odb , const char * section ,
const char * name , const char * value )
2020-03-26 19:43:52 -05:00
{
2021-02-18 19:36:52 -06:00
odb - > set_option < std : : string > ( section , name , value ) ;
2020-03-26 19:43:52 -05:00
}
2020-04-04 16:23:55 -05:00
const QofInstance *
2021-02-18 19:27:37 -06:00
gnc_option_db_lookup_qofinstance_value ( GncOptionDB * odb , const char * section ,
const char * name )
2020-04-04 16:23:55 -05:00
{
2021-02-18 19:27:37 -06:00
auto option { odb - > find_option ( section , name ) } ;
2023-01-23 13:22:35 -06:00
if ( option )
return option - > get_value < const QofInstance * > ( ) ;
else
return nullptr ;
2020-04-04 16:23:55 -05:00
}
2020-04-04 16:34:45 -05:00
// Force creation of templates
2022-09-14 19:39:21 -05:00
template void gnc_register_number_range_option ( GncOptionDB * db ,
2020-04-04 16:34:45 -05:00
const char * section , const char * name ,
const char * key , const char * doc_string ,
int value , int min , int max , int step ) ;
2022-09-14 19:39:21 -05:00
template void gnc_register_number_range_option ( GncOptionDB * db ,
2020-04-04 16:34:45 -05:00
const char * section , const char * name ,
const char * key , const char * doc_string ,
double value , double min ,
double max , double step ) ;