2021-06-20 00:57:27 +12:00
/* Copyright 2021 Aristocratos (jakob@qvantnet.com)
Licensed under the Apache License , Version 2.0 ( the " License " ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
2023-07-27 00:38:48 +12:00
http : //www.apache.org/licenses/LICENSE-2.0
2021-06-20 00:57:27 +12:00
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an " AS IS " BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
indent = tab
tab - size = 4
*/
# include <array>
# include <atomic>
# include <fstream>
2023-07-28 00:17:54 +12:00
# include <ranges>
2021-09-02 07:40:13 +12:00
# include <string_view>
2021-06-20 00:57:27 +12:00
2023-07-28 00:17:54 +12:00
# include <fmt/core.h>
2023-07-27 00:34:15 +12:00
# include "btop_config.hpp"
# include "btop_shared.hpp"
# include "btop_tools.hpp"
2021-06-20 00:57:27 +12:00
2022-10-03 10:29:05 +13:00
using std : : array ;
using std : : atomic ;
using std : : string_view ;
2021-06-20 00:57:27 +12:00
namespace fs = std : : filesystem ;
namespace rng = std : : ranges ;
2022-10-03 10:29:05 +13:00
using namespace std : : literals ;
2021-06-20 00:57:27 +12:00
using namespace Tools ;
//* Functions and variables for reading and writing the btop config file
namespace Config {
2021-07-21 13:17:34 +12:00
atomic < bool > locked ( false ) ;
2021-10-17 10:52:06 +13:00
atomic < bool > writelock ( false ) ;
2021-07-21 13:17:34 +12:00
bool write_new ;
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
const vector < array < string , 2 > > descriptions = {
2021-09-13 01:58:23 +12:00
{ " color_theme " , " #* Name of a btop++/bpytop/bashtop formatted \" .theme \" file, \" Default \" and \" TTY \" for builtin themes. \n "
" #* Themes should be placed in \" ../share/btop/themes \" relative to binary or \" $HOME/.config/btop/themes \" " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " theme_background " , " #* If the theme set background should be shown, set to False if you want terminal background transparency. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " truecolor " , " #* Sets if 24-bit truecolor should be used, will convert 24-bit colors to 256 color (6x6x6 color cube) if false. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " force_tty " , " #* Set to true to force tty mode regardless if a real tty has been detected or not. \n "
" #* Will force 16-color mode and TTY theme, set all graph symbols to \" tty \" and swap out other non tty friendly symbols. " } ,
2021-06-21 08:07:04 +12:00
2021-09-19 00:42:53 +12:00
{ " presets " , " #* Define presets for the layout of the boxes. Preset 0 is always all boxes shown with default settings. Max 9 presets. \n "
2021-12-14 01:45:22 +13:00
" #* Format: \" box_name:P:G,box_name:P:G \" P=(0 or 1) for alternate positions, G=graph symbol to use for box. \n "
2022-10-16 14:19:50 +13:00
" #* Use whitespace \" \" as separator between different presets. \n "
2021-09-19 00:42:53 +12:00
" #* Example: \" cpu:0:default,mem:0:tty,proc:1:default cpu:0:braille,proc:0:tty \" " } ,
2022-02-22 06:15:38 +13:00
{ " vim_keys " , " #* Set to True to enable \" h,j,k,l,g,G \" keys for directional control in lists. \n "
2021-10-13 04:34:52 +13:00
" #* Conflicting keys for h: \" help \" and k: \" kill \" is accessible while holding shift. " } ,
2021-08-23 02:04:01 +12:00
{ " rounded_corners " , " #* Rounded corners on boxes, is ignored if TTY mode is ON. " } ,
2021-07-21 13:17:34 +12:00
{ " graph_symbol " , " #* Default symbols to use for graph creation, \" braille \" , \" block \" or \" tty \" . \n "
" #* \" braille \" offers the highest resolution but might not be included in all fonts. \n "
" #* \" block \" has half the resolution of braille but uses more common characters. \n "
" #* \" tty \" uses only 3 different symbols but will work with most fonts and should work in a real TTY. \n "
" #* Note that \" tty \" only has half the horizontal resolution of the other two, so will show a shorter historical view. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " graph_symbol_cpu " , " # Graph symbol to use for graphs in cpu box, \" default \" , \" braille \" , \" block \" or \" tty \" . " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " graph_symbol_mem " , " # Graph symbol to use for graphs in cpu box, \" default \" , \" braille \" , \" block \" or \" tty \" . " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " graph_symbol_net " , " # Graph symbol to use for graphs in cpu box, \" default \" , \" braille \" , \" block \" or \" tty \" . " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " graph_symbol_proc " , " # Graph symbol to use for graphs in cpu box, \" default \" , \" braille \" , \" block \" or \" tty \" . " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " shown_boxes " , " #* Manually set which boxes to show. Available values are \" cpu mem net proc \" , separate values with whitespace. " } ,
2021-06-21 08:07:04 +12:00
2021-08-04 09:47:46 +12:00
{ " update_ms " , " #* Update time in milliseconds, recommended 2000 ms or above for better sample times for graphs. " } ,
2021-06-21 08:07:04 +12:00
2022-02-24 04:49:44 +13:00
{ " proc_sorting " , " #* Processes sorting, \" pid \" \" program \" \" arguments \" \" threads \" \" user \" \" memory \" \" cpu lazy \" \" cpu direct \" , \n "
" #* \" cpu lazy \" sorts top process over time (easier to follow), \" cpu direct \" updates top process directly. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " proc_reversed " , " #* Reverse sorting order, True or False. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " proc_tree " , " #* Show processes as a tree. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " proc_colors " , " #* Use the cpu graph colors in the process list. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " proc_gradient " , " #* Use a darkening gradient in the process list. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " proc_per_core " , " #* If process cpu usage should be of the core it's running on or usage of the total available cpu power. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " proc_mem_bytes " , " #* Show process memory as bytes instead of percent. " } ,
2021-06-21 08:07:04 +12:00
2022-07-30 02:18:06 +12:00
{ " proc_cpu_graphs " , " #* Show cpu graph for each process. " } ,
2021-08-04 09:47:46 +12:00
{ " proc_info_smaps " , " #* Use /proc/[pid]/smaps for memory information in the process info box (very slow but more accurate) " } ,
2021-07-26 11:06:34 +12:00
2021-07-30 09:40:56 +12:00
{ " proc_left " , " #* Show proc box on left side of screen instead of right. " } ,
2023-07-27 00:38:48 +12:00
{ " proc_filter_kernel " , " #* (Linux) Filter processes tied to the Linux kernel(similar behavior to htop). " } ,
2022-05-21 08:35:41 +12:00
2023-09-15 09:27:05 +12:00
{ " proc_aggregate " , " #* In tree-view, always accumulate child process resources in the parent process. " } ,
2021-07-21 13:17:34 +12:00
{ " cpu_graph_upper " , " #* Sets the CPU stat shown in upper half of the CPU graph, \" total \" is always available. \n "
" #* Select from a list of detected attributes from the options menu. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " cpu_graph_lower " , " #* Sets the CPU stat shown in lower half of the CPU graph, \" total \" is always available. \n "
" #* Select from a list of detected attributes from the options menu. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " cpu_invert_lower " , " #* Toggles if the lower CPU graph should be inverted. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " cpu_single_graph " , " #* Set to True to completely disable the lower CPU graph. " } ,
2021-06-21 08:07:04 +12:00
2021-07-30 09:40:56 +12:00
{ " cpu_bottom " , " #* Show cpu box at bottom of screen instead of top. " } ,
2021-07-21 13:17:34 +12:00
{ " show_uptime " , " #* Shows the system uptime in the CPU box. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " check_temp " , " #* Show cpu temperature. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " cpu_sensor " , " #* Which sensor to use for cpu temperature, use options menu to select from list of available sensors. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " show_coretemp " , " #* Show temperatures for cpu cores also if check_temp is True and sensors has been found. " } ,
2021-06-21 08:07:04 +12:00
2021-08-04 09:47:46 +12:00
{ " cpu_core_map " , " #* Set a custom mapping between core and coretemp, can be needed on certain cpus to get correct temperature for correct core. \n "
2021-09-18 00:25:54 +12:00
" #* Use lm-sensors or similar to see which cores are reporting temperatures on your machine. \n "
2021-08-04 09:47:46 +12:00
" #* Format \" x:y \" x=core with wrong temp, y=core with correct temp, use space as separator between multiple entries. \n "
" #* Example: \" 4:0 5:1 6:3 \" " } ,
2021-07-21 13:17:34 +12:00
{ " temp_scale " , " #* Which temperature scale to use, available values: \" celsius \" , \" fahrenheit \" , \" kelvin \" and \" rankine \" . " } ,
2021-06-21 08:07:04 +12:00
2022-01-17 01:39:50 +13:00
{ " base_10_sizes " , " #* Use base 10 for bits/bytes sizes, KB = 1000 instead of KiB = 1024. " } ,
2021-07-21 13:17:34 +12:00
{ " show_cpu_freq " , " #* Show CPU frequency. " } ,
2021-06-21 08:07:04 +12:00
2021-09-02 07:40:13 +12:00
{ " clock_format " , " #* Draw a clock at top of screen, formatting according to strftime, empty string to disable. \n "
" #* Special formatting: /host = hostname | /user = username | /uptime = system uptime " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " background_update " , " #* Update main ui in background when menus are showing, set this to false if the menus is flickering too much for comfort. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " custom_cpu_name " , " #* Custom cpu model name, empty string to disable. " } ,
2021-06-21 08:07:04 +12:00
2021-08-11 06:20:33 +12:00
{ " disks_filter " , " #* Optional filter for shown disks, should be full path of a mountpoint, separate multiple values with whitespace \" \" . \n "
" #* Begin line with \" exclude= \" to change to exclude filter, otherwise defaults to \" most include \" filter. Example: disks_filter= \" exclude=/boot /home/user \" . " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " mem_graphs " , " #* Show graphs instead of meters for memory values. " } ,
2021-06-21 08:07:04 +12:00
2021-07-30 09:40:56 +12:00
{ " mem_below_net " , " #* Show mem box below net box instead of above. " } ,
2022-04-30 15:08:00 +12:00
{ " zfs_arc_cached " , " #* Count ZFS ARC in cached and available memory. " } ,
2021-07-21 13:17:34 +12:00
{ " show_swap " , " #* If swap memory should be shown in memory box. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " swap_disk " , " #* Show swap as a disk, ignores show_swap value above, inserts itself after first disk. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " show_disks " , " #* If mem box should be split to also show disks info. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " only_physical " , " #* Filter out non physical disks. Set this to False to include network disks, RAM disks and similar. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " use_fstab " , " #* Read disks list from /etc/fstab. This also disables only_physical. " } ,
2021-06-21 08:07:04 +12:00
2022-07-12 04:08:25 +12:00
{ " zfs_hide_datasets " , " #* Setting this to True will hide all datasets, and only show ZFS pools. (IO stats will be calculated per-pool) " } ,
2022-07-02 03:35:41 +12:00
2022-02-13 12:33:20 +13:00
{ " disk_free_priv " , " #* Set to true to show available disk space for privileged users. " } ,
2021-09-13 01:58:23 +12:00
{ " show_io_stat " , " #* Toggles if io activity % (disk busy time) should be shown in regular disk usage view. " } ,
2021-06-21 08:07:04 +12:00
2021-09-13 01:58:23 +12:00
{ " io_mode " , " #* Toggles io mode for disks, showing big graphs for disk read/write speeds. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " io_graph_combined " , " #* Set to True to show combined read/write io graphs in io mode. " } ,
2021-06-21 08:07:04 +12:00
2021-09-18 00:25:54 +12:00
{ " io_graph_speeds " , " #* Set the top speed for the io graphs in MiB/s (100 by default), use format \" mountpoint:speed \" separate disks with whitespace \" \" . \n "
2021-08-11 06:20:33 +12:00
" #* Example: \" /mnt/media:100 /:20 /boot:1 \" . " } ,
2021-06-21 08:07:04 +12:00
2021-08-16 09:20:55 +12:00
{ " net_download " , " #* Set fixed values for network graphs in Mebibits. Is only used if net_auto is also set to False. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " net_upload " , " " } ,
2021-06-21 08:07:04 +12:00
2021-08-16 09:20:55 +12:00
{ " net_auto " , " #* Use network graphs auto rescaling mode, ignores any values set above and rescales down to 10 Kibibytes at the lowest. " } ,
2021-06-21 08:07:04 +12:00
2021-08-16 09:20:55 +12:00
{ " net_sync " , " #* Sync the auto scaling for download and upload to whichever currently has the highest scale. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " net_iface " , " #* Starts with the Network Interface specified here. " } ,
2021-06-21 08:07:04 +12:00
2021-07-21 13:17:34 +12:00
{ " show_battery " , " #* Show battery stats in top right if battery is present. " } ,
2021-06-20 00:57:27 +12:00
2021-10-18 09:26:43 +13:00
{ " selected_battery " , " #* Which battery to use if multiple are present. \" Auto \" for auto detection. " } ,
2021-09-23 03:38:06 +12:00
{ " log_level " , " #* Set loglevel for \" ~/.config/btop/btop.log \" levels are: \" ERROR \" \" WARNING \" \" INFO \" \" DEBUG \" . \n "
2021-07-21 13:17:34 +12:00
" #* The level set includes all lower levels, i.e. \" DEBUG \" will show all logging info. " }
} ;
2021-06-20 00:57:27 +12:00
2023-07-28 00:17:54 +12:00
unordered_flat_map < std : : string_view , string > strings = {
2021-07-21 13:17:34 +12:00
{ " color_theme " , " Default " } ,
{ " shown_boxes " , " cpu mem net proc " } ,
{ " graph_symbol " , " braille " } ,
2021-09-19 00:42:53 +12:00
{ " presets " , " cpu:1:default,proc:0:default cpu:0:default,mem:0:default,net:0:default cpu:0:block,net:0:tty " } ,
2021-07-21 13:17:34 +12:00
{ " graph_symbol_cpu " , " default " } ,
{ " graph_symbol_mem " , " default " } ,
{ " graph_symbol_net " , " default " } ,
{ " graph_symbol_proc " , " default " } ,
{ " proc_sorting " , " cpu lazy " } ,
{ " cpu_graph_upper " , " total " } ,
{ " cpu_graph_lower " , " total " } ,
{ " cpu_sensor " , " Auto " } ,
2021-10-18 09:26:43 +13:00
{ " selected_battery " , " Auto " } ,
2021-08-04 09:47:46 +12:00
{ " cpu_core_map " , " " } ,
2021-07-21 13:17:34 +12:00
{ " temp_scale " , " celsius " } ,
2021-08-23 02:04:01 +12:00
{ " clock_format " , " %X " } ,
2021-07-21 13:17:34 +12:00
{ " custom_cpu_name " , " " } ,
{ " disks_filter " , " " } ,
{ " io_graph_speeds " , " " } ,
{ " net_iface " , " " } ,
{ " log_level " , " WARNING " } ,
{ " proc_filter " , " " } ,
{ " proc_command " , " " } ,
2021-09-02 07:40:13 +12:00
{ " selected_name " , " " } ,
2021-07-21 13:17:34 +12:00
} ;
2023-07-28 00:17:54 +12:00
unordered_flat_map < std : : string_view , string > stringsTmp ;
2021-07-21 13:17:34 +12:00
2023-07-28 00:17:54 +12:00
unordered_flat_map < std : : string_view , bool > bools = {
2021-07-21 13:17:34 +12:00
{ " theme_background " , true } ,
{ " truecolor " , true } ,
2021-08-23 02:04:01 +12:00
{ " rounded_corners " , true } ,
2021-07-21 13:17:34 +12:00
{ " proc_reversed " , false } ,
{ " proc_tree " , false } ,
{ " proc_colors " , true } ,
{ " proc_gradient " , true } ,
2022-01-17 00:43:24 +13:00
{ " proc_per_core " , false } ,
2021-07-21 13:17:34 +12:00
{ " proc_mem_bytes " , true } ,
2022-07-30 02:18:06 +12:00
{ " proc_cpu_graphs " , true } ,
2021-07-26 11:06:34 +12:00
{ " proc_info_smaps " , false } ,
2021-07-30 09:40:56 +12:00
{ " proc_left " , false } ,
2023-07-27 00:38:48 +12:00
{ " proc_filter_kernel " , false } ,
2021-07-21 13:17:34 +12:00
{ " cpu_invert_lower " , true } ,
{ " cpu_single_graph " , false } ,
2021-07-30 09:40:56 +12:00
{ " cpu_bottom " , false } ,
2021-07-21 13:17:34 +12:00
{ " show_uptime " , true } ,
{ " check_temp " , true } ,
{ " show_coretemp " , true } ,
{ " show_cpu_freq " , true } ,
{ " background_update " , true } ,
{ " mem_graphs " , true } ,
2021-07-30 09:40:56 +12:00
{ " mem_below_net " , false } ,
2022-04-30 15:08:00 +12:00
{ " zfs_arc_cached " , true } ,
2021-07-21 13:17:34 +12:00
{ " show_swap " , true } ,
{ " swap_disk " , true } ,
{ " show_disks " , true } ,
{ " only_physical " , true } ,
2021-09-27 06:35:09 +13:00
{ " use_fstab " , true } ,
2022-07-12 04:08:25 +12:00
{ " zfs_hide_datasets " , false } ,
2021-07-21 13:17:34 +12:00
{ " show_io_stat " , true } ,
{ " io_mode " , false } ,
2022-01-17 01:39:50 +13:00
{ " base_10_sizes " , false } ,
2021-07-21 13:17:34 +12:00
{ " io_graph_combined " , false } ,
{ " net_auto " , true } ,
2022-05-29 06:48:02 +12:00
{ " net_sync " , true } ,
2021-07-21 13:17:34 +12:00
{ " show_battery " , true } ,
2021-10-13 04:34:52 +13:00
{ " vim_keys " , false } ,
2021-07-21 13:17:34 +12:00
{ " tty_mode " , false } ,
2022-02-13 12:33:20 +13:00
{ " disk_free_priv " , false } ,
2021-07-21 13:17:34 +12:00
{ " force_tty " , false } ,
{ " lowcolor " , false } ,
{ " show_detailed " , false } ,
{ " proc_filtering " , false } ,
2023-09-15 09:27:05 +12:00
{ " proc_aggregate " , false } ,
2021-07-21 13:17:34 +12:00
} ;
2023-07-28 00:17:54 +12:00
unordered_flat_map < std : : string_view , bool > boolsTmp ;
2021-07-21 13:17:34 +12:00
2023-07-28 00:17:54 +12:00
unordered_flat_map < std : : string_view , int > ints = {
2021-07-21 13:17:34 +12:00
{ " update_ms " , 2000 } ,
2021-08-16 09:20:55 +12:00
{ " net_download " , 100 } ,
{ " net_upload " , 100 } ,
2021-07-21 13:17:34 +12:00
{ " detailed_pid " , 0 } ,
{ " selected_pid " , 0 } ,
2022-07-03 22:37:54 +12:00
{ " selected_depth " , 0 } ,
2021-07-21 13:17:34 +12:00
{ " proc_start " , 0 } ,
{ " proc_selected " , 0 } ,
2021-07-26 11:06:34 +12:00
{ " proc_last_selected " , 0 } ,
2021-07-21 13:17:34 +12:00
} ;
2023-07-28 00:17:54 +12:00
unordered_flat_map < std : : string_view , int > intsTmp ;
2021-07-21 13:17:34 +12:00
2023-07-28 00:17:54 +12:00
bool _locked ( const std : : string_view name ) {
2021-10-17 10:52:06 +13:00
atomic_wait ( writelock , true ) ;
2021-07-21 13:17:34 +12:00
if ( not write_new and rng : : find_if ( descriptions , [ & name ] ( const auto & a ) { return a . at ( 0 ) = = name ; } ) ! = descriptions . end ( ) )
write_new = true ;
return locked . load ( ) ;
2021-06-20 00:57:27 +12:00
}
fs : : path conf_dir ;
fs : : path conf_file ;
2021-10-18 09:26:43 +13:00
vector < string > available_batteries = { " Auto " } ;
2021-07-19 01:44:32 +12:00
vector < string > current_boxes ;
2021-09-19 00:42:53 +12:00
vector < string > preset_list = { " cpu:0:default,mem:0:default,net:0:default,proc:0:default " } ;
int current_preset = - 1 ;
bool presetsValid ( const string & presets ) {
vector < string > new_presets = { preset_list . at ( 0 ) } ;
for ( int x = 0 ; const auto & preset : ssplit ( presets ) ) {
if ( + + x > 9 ) {
validError = " Too many presets entered! " ;
return false ;
}
for ( int y = 0 ; const auto & box : ssplit ( preset , ' , ' ) ) {
if ( + + y > 4 ) {
validError = " Too many boxes entered for preset! " ;
return false ;
}
const auto & vals = ssplit ( box , ' : ' ) ;
if ( vals . size ( ) ! = 3 ) {
validError = " Malformatted preset in config value presets! " ;
return false ;
}
if ( not is_in ( vals . at ( 0 ) , " cpu " , " mem " , " net " , " proc " ) ) {
validError = " Invalid box name in config value presets! " ;
return false ;
}
if ( not is_in ( vals . at ( 1 ) , " 0 " , " 1 " ) ) {
validError = " Invalid position value in config value presets! " ;
return false ;
}
if ( not v_contains ( valid_graph_symbols_def , vals . at ( 2 ) ) ) {
validError = " Invalid graph name in config value presets! " ;
return false ;
}
}
new_presets . push_back ( preset ) ;
}
2023-05-24 01:11:20 +12:00
preset_list = std : : move ( new_presets ) ;
2021-09-19 00:42:53 +12:00
return true ;
}
//* Apply selected preset
void apply_preset ( const string & preset ) {
string boxes ;
2021-09-21 04:20:30 +12:00
2021-09-19 00:42:53 +12:00
for ( const auto & box : ssplit ( preset , ' , ' ) ) {
const auto & vals = ssplit ( box , ' : ' ) ;
boxes + = vals . at ( 0 ) + ' ' ;
2021-09-21 04:20:30 +12:00
}
if ( not boxes . empty ( ) ) boxes . pop_back ( ) ;
auto min_size = Term : : get_min_size ( boxes ) ;
if ( Term : : width < min_size . at ( 0 ) or Term : : height < min_size . at ( 1 ) ) {
return ;
}
for ( const auto & box : ssplit ( preset , ' , ' ) ) {
const auto & vals = ssplit ( box , ' : ' ) ;
2021-09-19 00:42:53 +12:00
if ( vals . at ( 0 ) = = " cpu " ) set ( " cpu_bottom " , ( vals . at ( 1 ) = = " 0 " ? false : true ) ) ;
else if ( vals . at ( 0 ) = = " mem " ) set ( " mem_below_net " , ( vals . at ( 1 ) = = " 0 " ? false : true ) ) ;
else if ( vals . at ( 0 ) = = " proc " ) set ( " proc_left " , ( vals . at ( 1 ) = = " 0 " ? false : true ) ) ;
set ( " graph_symbol_ " + vals . at ( 0 ) , vals . at ( 2 ) ) ;
}
2021-09-21 04:20:30 +12:00
2021-09-19 00:42:53 +12:00
if ( check_boxes ( boxes ) ) set ( " shown_boxes " , boxes ) ;
}
2021-07-19 01:44:32 +12:00
2021-07-24 12:13:26 +12:00
void lock ( ) {
2021-10-17 10:52:06 +13:00
atomic_wait ( writelock ) ;
2021-07-24 12:13:26 +12:00
locked = true ;
2021-06-20 00:57:27 +12:00
}
2021-09-13 01:58:23 +12:00
string validError ;
2023-07-28 00:17:54 +12:00
bool intValid ( const std : : string_view name , const string & value ) {
2021-09-13 01:58:23 +12:00
int i_value ;
try {
i_value = stoi ( value ) ;
}
catch ( const std : : invalid_argument & ) {
validError = " Invalid numerical value! " ;
return false ;
}
catch ( const std : : out_of_range & ) {
validError = " Value out of range! " ;
return false ;
}
2021-09-18 00:25:54 +12:00
catch ( const std : : exception & e ) {
2023-07-27 00:38:48 +12:00
validError = string { e . what ( ) } ;
2021-09-18 00:25:54 +12:00
return false ;
}
2021-09-13 01:58:23 +12:00
if ( name = = " update_ms " and i_value < 100 )
validError = " Config value update_ms set too low (<100). " ;
else if ( name = = " update_ms " and i_value > 86400000 )
validError = " Config value update_ms set too high (>86400000). " ;
else
return true ;
return false ;
}
2023-07-28 00:17:54 +12:00
bool stringValid ( const std : : string_view name , const string & value ) {
2021-09-13 01:58:23 +12:00
if ( name = = " log_level " and not v_contains ( Logger : : log_levels , value ) )
validError = " Invalid log_level: " + value ;
else if ( name = = " graph_symbol " and not v_contains ( valid_graph_symbols , value ) )
validError = " Invalid graph symbol identifier: " + value ;
else if ( name . starts_with ( " graph_symbol_ " ) and ( value ! = " default " and not v_contains ( valid_graph_symbols , value ) ) )
2023-07-28 00:17:54 +12:00
validError = fmt : : format ( " Invalid graph symbol identifier for {}: {} " , name , value ) ;
2021-09-13 01:58:23 +12:00
else if ( name = = " shown_boxes " and not value . empty ( ) and not check_boxes ( value ) )
validError = " Invalid box name(s) in shown_boxes! " ;
2021-09-19 00:42:53 +12:00
else if ( name = = " presets " and not presetsValid ( value ) )
return false ;
2021-09-13 01:58:23 +12:00
else if ( name = = " cpu_core_map " ) {
const auto maps = ssplit ( value ) ;
bool all_good = true ;
for ( const auto & map : maps ) {
const auto map_split = ssplit ( map , ' : ' ) ;
if ( map_split . size ( ) ! = 2 )
all_good = false ;
else if ( not isint ( map_split . at ( 0 ) ) or not isint ( map_split . at ( 1 ) ) )
all_good = false ;
if ( not all_good ) {
validError = " Invalid formatting of cpu_core_map! " ;
return false ;
}
}
return true ;
}
else if ( name = = " io_graph_speeds " ) {
const auto maps = ssplit ( value ) ;
bool all_good = true ;
for ( const auto & map : maps ) {
const auto map_split = ssplit ( map , ' : ' ) ;
if ( map_split . size ( ) ! = 2 )
all_good = false ;
else if ( map_split . at ( 0 ) . empty ( ) or not isint ( map_split . at ( 1 ) ) )
all_good = false ;
if ( not all_good ) {
validError = " Invalid formatting of io_graph_speeds! " ;
return false ;
}
}
return true ;
}
else
return true ;
return false ;
}
2023-07-28 00:17:54 +12:00
string getAsString ( const std : : string_view name ) {
2021-09-13 01:58:23 +12:00
if ( bools . contains ( name ) )
return ( bools . at ( name ) ? " True " : " False " ) ;
else if ( ints . contains ( name ) )
return to_string ( ints . at ( name ) ) ;
else if ( strings . contains ( name ) )
return strings . at ( name ) ;
return " " ;
}
2023-07-28 00:17:54 +12:00
void flip ( const std : : string_view name ) {
2021-06-20 00:57:27 +12:00
if ( _locked ( name ) ) {
2021-06-22 08:52:55 +12:00
if ( boolsTmp . contains ( name ) ) boolsTmp . at ( name ) = not boolsTmp . at ( name ) ;
else boolsTmp . insert_or_assign ( name , ( not bools . at ( name ) ) ) ;
2021-06-20 00:57:27 +12:00
}
2021-06-22 08:52:55 +12:00
else bools . at ( name ) = not bools . at ( name ) ;
2021-06-20 00:57:27 +12:00
}
2021-07-21 13:17:34 +12:00
void unlock ( ) {
2021-07-01 08:28:12 +12:00
if ( not locked ) return ;
2021-08-11 06:20:33 +12:00
atomic_wait ( Runner : : active ) ;
2021-10-17 10:52:06 +13:00
atomic_lock lck ( writelock , true ) ;
2021-07-21 13:17:34 +12:00
try {
if ( Proc : : shown ) {
ints . at ( " selected_pid " ) = Proc : : selected_pid ;
2021-09-02 07:40:13 +12:00
strings . at ( " selected_name " ) = Proc : : selected_name ;
2021-07-21 13:17:34 +12:00
ints . at ( " proc_start " ) = Proc : : start ;
ints . at ( " proc_selected " ) = Proc : : selected ;
2022-07-03 22:37:54 +12:00
ints . at ( " selected_depth " ) = Proc : : selected_depth ;
2021-07-21 13:17:34 +12:00
}
2021-06-20 00:57:27 +12:00
2021-07-21 13:17:34 +12:00
for ( auto & item : stringsTmp ) {
strings . at ( item . first ) = item . second ;
}
stringsTmp . clear ( ) ;
2021-06-20 00:57:27 +12:00
2021-07-21 13:17:34 +12:00
for ( auto & item : intsTmp ) {
ints . at ( item . first ) = item . second ;
}
intsTmp . clear ( ) ;
2021-06-20 00:57:27 +12:00
2021-07-21 13:17:34 +12:00
for ( auto & item : boolsTmp ) {
bools . at ( item . first ) = item . second ;
}
boolsTmp . clear ( ) ;
}
catch ( const std : : exception & e ) {
2023-07-27 00:38:48 +12:00
Global : : exit_error_msg = " Exception during Config::unlock() : " + string { e . what ( ) } ;
2021-11-14 11:31:01 +13:00
clean_quit ( 1 ) ;
2021-06-20 00:57:27 +12:00
}
locked = false ;
}
2021-07-24 12:13:26 +12:00
bool check_boxes ( const string & boxes ) {
2021-07-19 01:44:32 +12:00
auto new_boxes = ssplit ( boxes ) ;
for ( auto & box : new_boxes ) {
2021-07-04 11:18:48 +12:00
if ( not v_contains ( valid_boxes , box ) ) return false ;
}
2023-05-24 01:11:20 +12:00
current_boxes = std : : move ( new_boxes ) ;
2021-07-04 11:18:48 +12:00
return true ;
}
2021-07-30 09:40:56 +12:00
void toggle_box ( const string & box ) {
2021-09-21 04:20:30 +12:00
auto old_boxes = current_boxes ;
2021-08-18 08:33:21 +12:00
auto box_pos = rng : : find ( current_boxes , box ) ;
if ( box_pos = = current_boxes . end ( ) )
2021-07-30 09:40:56 +12:00
current_boxes . push_back ( box ) ;
else
2021-08-18 08:33:21 +12:00
current_boxes . erase ( box_pos ) ;
2021-07-30 09:40:56 +12:00
string new_boxes ;
if ( not current_boxes . empty ( ) ) {
for ( const auto & b : current_boxes ) new_boxes + = b + ' ' ;
new_boxes . pop_back ( ) ;
}
2021-09-21 04:20:30 +12:00
auto min_size = Term : : get_min_size ( new_boxes ) ;
if ( Term : : width < min_size . at ( 0 ) or Term : : height < min_size . at ( 1 ) ) {
current_boxes = old_boxes ;
return ;
}
2021-07-30 09:40:56 +12:00
Config : : set ( " shown_boxes " , new_boxes ) ;
}
void load ( const fs : : path & conf_file , vector < string > & load_warnings ) {
2021-06-20 00:57:27 +12:00
if ( conf_file . empty ( ) )
return ;
2021-06-22 08:52:55 +12:00
else if ( not fs : : exists ( conf_file ) ) {
2021-06-20 00:57:27 +12:00
write_new = true ;
return ;
}
std : : ifstream cread ( conf_file ) ;
if ( cread . good ( ) ) {
vector < string > valid_names ;
for ( auto & n : descriptions )
valid_names . push_back ( n [ 0 ] ) ;
2021-11-05 00:36:23 +13:00
if ( string v_string ; cread . peek ( ) ! = ' # ' or ( getline ( cread , v_string , ' \n ' ) and not s_contains ( v_string , Global : : Version ) ) )
2021-06-20 00:57:27 +12:00
write_new = true ;
2021-06-22 08:52:55 +12:00
while ( not cread . eof ( ) ) {
2021-06-20 00:57:27 +12:00
cread > > std : : ws ;
if ( cread . peek ( ) = = ' # ' ) {
cread . ignore ( SSmax , ' \n ' ) ;
continue ;
}
string name , value ;
getline ( cread , name , ' = ' ) ;
2021-07-19 01:44:32 +12:00
if ( name . ends_with ( ' ' ) ) name = trim ( name ) ;
2021-06-22 08:52:55 +12:00
if ( not v_contains ( valid_names , name ) ) {
2021-06-20 00:57:27 +12:00
cread . ignore ( SSmax , ' \n ' ) ;
continue ;
}
2021-07-19 01:44:32 +12:00
cread > > std : : ws ;
2021-06-20 00:57:27 +12:00
if ( bools . contains ( name ) ) {
cread > > value ;
2021-06-22 08:52:55 +12:00
if ( not isbool ( value ) )
2021-07-30 09:40:56 +12:00
load_warnings . push_back ( " Got an invalid bool value for config name: " + name ) ;
2021-06-20 00:57:27 +12:00
else
bools . at ( name ) = stobool ( value ) ;
}
else if ( ints . contains ( name ) ) {
cread > > value ;
2021-06-22 08:52:55 +12:00
if ( not isint ( value ) )
2021-07-30 09:40:56 +12:00
load_warnings . push_back ( " Got an invalid integer value for config name: " + name ) ;
2021-09-13 01:58:23 +12:00
else if ( not intValid ( name , value ) ) {
load_warnings . push_back ( validError ) ;
2021-08-23 02:04:01 +12:00
}
2021-06-20 00:57:27 +12:00
else
ints . at ( name ) = stoi ( value ) ;
}
else if ( strings . contains ( name ) ) {
if ( cread . peek ( ) = = ' " ' ) {
cread . ignore ( 1 ) ;
getline ( cread , value , ' " ' ) ;
}
else cread > > value ;
2021-09-13 01:58:23 +12:00
if ( not stringValid ( name , value ) )
load_warnings . push_back ( validError ) ;
2021-06-20 00:57:27 +12:00
else
strings . at ( name ) = value ;
}
cread . ignore ( SSmax , ' \n ' ) ;
}
2021-07-30 09:40:56 +12:00
if ( not load_warnings . empty ( ) ) write_new = true ;
2021-06-20 00:57:27 +12:00
}
}
2021-07-21 13:17:34 +12:00
void write ( ) {
2021-06-22 08:52:55 +12:00
if ( conf_file . empty ( ) or not write_new ) return ;
2021-06-20 00:57:27 +12:00
Logger : : debug ( " Writing new config file " ) ;
2021-11-03 09:10:41 +13:00
if ( geteuid ( ) ! = Global : : real_uid and seteuid ( Global : : real_uid ) ! = 0 ) return ;
2021-06-20 00:57:27 +12:00
std : : ofstream cwrite ( conf_file , std : : ios : : trunc ) ;
if ( cwrite . good ( ) ) {
cwrite < < " #? Config file for btop v. " < < Global : : Version ;
for ( auto [ name , description ] : descriptions ) {
2021-07-19 01:44:32 +12:00
cwrite < < " \n \n " < < ( description . empty ( ) ? " " : description + " \n " )
< < name < < " = " ;
if ( strings . contains ( name ) )
cwrite < < " \" " < < strings . at ( name ) < < " \" " ;
else if ( ints . contains ( name ) )
cwrite < < ints . at ( name ) ;
else if ( bools . contains ( name ) )
cwrite < < ( bools . at ( name ) ? " True " : " False " ) ;
2021-06-20 00:57:27 +12:00
}
}
}
2021-12-14 01:45:22 +13:00
}