Add gtk102

This commit is contained in:
daleclack 2021-08-12 10:56:18 +08:00
parent 7033314f38
commit 74f3bb9da1
6 changed files with 385 additions and 0 deletions

154
Gtkmm3/cfgfile2/cfgfile.cc Normal file
View File

@ -0,0 +1,154 @@
// A Test to read Config files
// This is a modified version
// The Config File Should be a text file
// and the content as follows
// key=value
#include "cfgfile.hh"
static void Trim(std::string &str){
if(str.empty()){//String is empty
return;
}
size_t i,start_pos,end_pos;
for(i=0;i<str.size();i++){//Get Start Position
if(!isspace(str[i])){
break;
}
}
if(i==str.size()){//Only Space and Tabs in string
return;
}
start_pos=i;
for(i=str.size()-1;i>=0;i--){//Get End Position
if(!isspace(str[i])){
break;
}
}
end_pos=i;
str=str.substr(start_pos,end_pos+1);
}
bool readCfgFile(std::string &cfgfilePath,conf_map &configs){
//Open The Config File and load config to map
std::fstream cfgfile;
cfgfile.open(cfgfilePath);
if(!cfgfile.is_open()){
std::cout<<"Failed to open the file!"<<std::endl;
return false;
}
//If Map is not empty,clear it
if(!configs.empty()){
configs.clear();
}
//Read each line of config file and get value
char tmp[1000];
while(!cfgfile.eof()){
cfgfile.getline(tmp,1000);
std::string line(tmp),value;
std::size_t pos = line.find('=');//Get the position of '='
if(pos == std::string::npos){//No Configs
continue;
}
std::string key=line.substr(0,pos);
value=line.substr(pos+1);
//Clear Spaces
Trim(key);Trim(value);
configs[key]=value;
}
cfgfile.close();
return true;
}
// Some Test Codes,for Test Purpose only.
// void readcfg(){
// //Input Config File Path and Key
// char filename[1000];
// std::string cfgkey;
// conf_map test_config;
// std::cout<<"Input Config File Name:";//Config File Name
// std::cin.get();//Clear the cin to read line
// std::cin.getline(filename,1000);
// std::cout<<"Input Config Key:";//Config Key
// std::cin>>cfgkey;
// //Get The Config
// if(readCfgFile(filename,test_config)){
// std::cout<<"The Config Of "<<cfgkey<<" is "<<test_config[cfgkey]<<std::endl;
// }else{
// std::cout<<"Failed to Read Config!"<<std::endl;
// }
// }
// void appendcfg(){
// //Input Config File Path and Key
// char filename[1000];
// std::string cfgkey,cfgvalue;
// std::cout<<"Input Config File Name:";
// std::cin.get();//Clear the cin to read line
// std::cin.getline(filename,1000);
// //Append Config
// std::fstream cfgfile;
// cfgfile.open(filename,std::ios_base::app);
// if(cfgfile.is_open()){
// std::cout<<"Input Config Key And Config Value:";
// std::cin>>cfgkey>>cfgvalue;
// cfgfile<<std::endl;
// cfgfile<<cfgkey<<"="<<cfgvalue;
// cfgfile.close();
// }else{
// std::cout<<"Config File Open Failed!"<<std::endl;
// }
// }
// void show_configs(){
// //Input Config File Path and Key
// char filename[1000];
// conf_map test_config;
// std::cout<<"Input Config File Name"<<std::endl;//Config File Name
// std::cin.get();//Clear the cin to read line
// std::cin.getline(filename,1000);
// //Get The Config and Show all Config in map
// if(readCfgFile(filename,test_config)){
// auto mite=test_config.begin();
// for(;mite!=test_config.end();mite++){
// std::cout<<mite->first<<"="<<mite->second<<std::endl;
// }
// }else{
// std::cout<<"Failed to Read Config!"<<std::endl;
// }
// }
// int main(int argc,char **argv){
// //Function Pointer to select mode
// pfun feature[]={readcfg,appendcfg,show_configs};
// //Get Selection and execute a mode
// int selection;
// std::cout<<"0.Read a Config 1.Append a Config 2.Show all Configs"<<std::endl<<"Selection a mode:";
// std::cin>>selection;
// feature[selection]();
// return 0;
// }

View File

@ -0,0 +1,10 @@
#pragma once
#include <iostream>
#include <fstream>
#include <string>
#include <map>
typedef std::map<std::string,std::string> conf_map;//Container of configs
bool readCfgFile(std::string &cfgfilePath,conf_map &configs);

View File

@ -0,0 +1,30 @@
#A Simple Project Test
project('gtk102', 'cpp',
default_options : ['c_std=c17', 'cpp_std=c++17'])
#Initalize variants
# gnome=import('gnome')
#Compile Resource
# gresources = gnome.compile_resources(
# 'resources', 'res/gtk91.resource.xml',
# source_dir: 'res',
# c_name: 'resources'
# )
#The Gtkmm Library as a dependency
gtkdep = dependency('gtkmm-3.0')
#Additional include dirs
dir_include = include_directories('..')
#Use Different Build Opinions in windows and Linux
if host_machine.system() == 'windows'
win=import('windows')
icon_res=win.compile_resources('../icon.rc')
executable('gtk102', icon_res, 'src/main.cc', 'src/MyWin.cc', '../cfgfile2/cfgfile.cc',
dependencies : gtkdep, win_subsystem : 'windows', include_directories : dir_include)
else
executable('gtk102', 'src/main.cc', 'src/MyWin.cc', '../cfgfile2/cfgfile.cc',
dependencies : gtkdep, include_directories : dir_include)
endif

View File

@ -0,0 +1,137 @@
#include "MyWin.hh"
MyWin::MyWin()
:main_box(Gtk::ORIENTATION_HORIZONTAL,5),
btn_box(Gtk::ORIENTATION_VERTICAL,5),
m_label("No Selection"),
btn_load("Load Config"),
btn_save("Save Config"),
btn_exit("Exit")
{
//Initalize window
set_icon_name("org.gtk.daleclack");
set_default_size(400,300);
//Add Widgets
scrolled.add(m_treeview);
scrolled.set_policy(Gtk::POLICY_AUTOMATIC,Gtk::POLICY_AUTOMATIC);
main_box.pack_start(scrolled);
//Buttons
btn_box.pack_start(m_label,Gtk::PACK_SHRINK);
btn_box.pack_start(btn_load,Gtk::PACK_SHRINK);
btn_box.pack_start(btn_save,Gtk::PACK_SHRINK);
btn_box.pack_start(btn_exit,Gtk::PACK_SHRINK);
btn_box.set_valign(Gtk::ALIGN_CENTER);
main_box.pack_start(btn_box,Gtk::PACK_SHRINK);
add(main_box);
//Create and add model
ref_liststore=Gtk::ListStore::create(m_columns);
m_treeview.set_model(ref_liststore);
m_treeview.append_column_editable("Key",m_columns.m_col_key);
m_treeview.append_column_editable("Value",m_columns.m_col_value);
selection=m_treeview.get_selection();
btn_exit.signal_clicked().connect(sigc::mem_fun(*this,&MyWin::hide));
btn_save.signal_clicked().connect(sigc::mem_fun(*this,&MyWin::btnsave_clicked));
btn_load.signal_clicked().connect(sigc::mem_fun(*this,&MyWin::btnload_clicked));
selection->signal_changed().connect(sigc::mem_fun(*this,&MyWin::selection_changed));
show_all_children();
}
void MyWin::selection_changed(){
auto row=*(selection->get_selected());
m_label.set_label(row[m_columns.m_col_value]);
}
void MyWin::btnload_clicked(){
dialog=Gtk::FileChooserNative::create("Open A Config File",*this,Gtk::FILE_CHOOSER_ACTION_OPEN,
"OK","Cancel");
dialog->signal_response().connect(sigc::mem_fun(*this,&MyWin::dialog_response));
auto filter_any=Gtk::FileFilter::create();
filter_any->add_pattern("*");
filter_any->set_name("Any Files");
dialog->add_filter(filter_any);
dialog->show();
}
void MyWin::dialog_response(int response_id){
if(response_id==Gtk::RESPONSE_ACCEPT){
auto filename=dialog->get_filename();
//Clear the liststore
ref_liststore->clear();
//If Configs is not empty,clear it
if(!my_configs.empty()){
my_configs.clear();
}
if(readCfgFile(filename,my_configs)){
auto mite=my_configs.begin();
for(;mite!=my_configs.end();mite++){
auto row=*(ref_liststore->append());
row[m_columns.m_col_key]=mite->first;
row[m_columns.m_col_value]=mite->second;
}
}
}
dialog.reset();
}
void MyWin::btnsave_clicked(){
dialog=Gtk::FileChooserNative::create("Open A Config File",*this,Gtk::FILE_CHOOSER_ACTION_SAVE,
"OK","Cancel");
dialog->signal_response().connect(sigc::mem_fun(*this,&MyWin::dialog_save_response));
auto filter_cfg=Gtk::FileFilter::create();
filter_cfg->add_pattern("*.cfg");
filter_cfg->set_name("Config Files");
dialog->add_filter(filter_cfg);
auto filter_any=Gtk::FileFilter::create();
filter_any->add_pattern("*");
filter_any->set_name("Any Files");
dialog->add_filter(filter_any);
dialog->show();
}
void MyWin::dialog_save_response(int response_id){
if(response_id==Gtk::RESPONSE_ACCEPT){
//Get Filename and open(create) a config file
std::string filename=dialog->get_filename();
std::fstream outfile;
outfile.open(filename,std::ios_base::out);
if(!outfile.is_open()){
dialog.reset();
std::cout<<"Error!";
return ;
}
//Write Key and Values
auto children=ref_liststore->children();
for(auto iter = children.begin();
iter != children.end(); iter++)
{
auto row=*iter;
outfile<<row[m_columns.m_col_key]<<"="<<row[m_columns.m_col_value]<<std::endl;
}
//Close the config file
outfile.close();
}
dialog.reset();
}

View File

@ -0,0 +1,47 @@
#pragma once
#include <gtkmm.h>
#include "../cfgfile2/cfgfile.hh"
class MyWin : public Gtk::Window{
public:
MyWin();
private:
//Model Columns
class ModelColumns : public Gtk::TreeModelColumnRecord{
public:
ModelColumns()
{add(m_col_key); add(m_col_value); }
Gtk::TreeModelColumn<Glib::ustring> m_col_key;
Gtk::TreeModelColumn<Glib::ustring> m_col_value;
};
ModelColumns m_columns;
Glib::RefPtr<Gtk::ListStore> ref_liststore;
Glib::RefPtr<Gtk::TreeSelection> selection;
//Child Widgets
Gtk::TreeView m_treeview;
Gtk::Box main_box,btn_box;
Gtk::ScrolledWindow scrolled;
Gtk::Label m_label;
Gtk::Button btn_load,btn_save,btn_exit;
Glib::RefPtr<Gtk::FileChooserNative> dialog;
//Keys and values for config
conf_map my_configs;
//Signal Handlers
void selection_changed();
void btnload_clicked();
void btnsave_clicked();
void dialog_response(int response_id);
void dialog_save_response(int response_id);
};

View File

@ -0,0 +1,7 @@
#include "MyWin.hh"
int main(int argc,char **argv){
auto app=Gtk::Application::create(argc,argv,"org.gtk.daleclack");
MyWin window;
return app->run(window);
}