code_app/app/scanner/config.cpp

432 lines
10 KiB
C++

#include "config.h"
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <sstream>
#include <iomanip>
#include <QDir>
#include <fcntl.h>
#include <sys/stat.h>
#include <QLatin1String>
#include <qtextcodec.h>
#include <string.h>
#include <QCoreApplication>
config::config() : ini_(NULL), file_(""), schem_jsn_(NULL)
{
}
config::~config()
{
if(ini_)
delete ini_;
if(schem_jsn_)
delete schem_jsn_;
}
QString config::get_scanner_config_file(void)
{
QString file(get_val("scanner", "schemes"));
if(file.length() == 0)
{
file = "scanner.schm";
ini_->setValue("schemes", file);
}
if(file[0] != '/')
{
std::string path(file_.toStdString());
path.erase(path.rfind('/') + 1);
path += file.toStdString();
file = QString::fromStdString(path);
}
return file;
}
void config::reload_schemes(void)
{
if(schem_jsn_)
{
delete schem_jsn_;
schem_jsn_ = NULL;
}
std::string jsntxt(""), org(config::read_mini_file(get_scanner_config_file()));
gb::base64 base64;
if(org.empty())
return;
jsntxt = base64.decode(org.c_str(), org.length());
schem_jsn_ = new gb::json();
if(!schem_jsn_->attach_text(&jsntxt[0]))
{
delete schem_jsn_;
schem_jsn_ = NULL;
}
}
QString config::self_path(void)
{
QString qexePath = QCoreApplication::applicationDirPath();
return qexePath;
}
std::string config::read_mini_file(QString file)
{
std::string f(file.toStdString()),
ret("");
FILE* src = fopen(f.c_str(), "rb");
if(src)
{
long l = 0;
char *buf = NULL;
fseek(src, 0, SEEK_END);
l = ftell(src);
fseek(src, 0, SEEK_SET);
buf = (char*)malloc(l + 4);
memset(buf, 0, l + 4);
fread(buf, 1, l, src);
fclose(src);
ret = buf;
free(buf);
}
return ret;
}
std::string config::device_to_config_dev_name(QString& dev_name)
{
std::string name(dev_name.toStdString());
size_t pos = name.find(" - ");
if(pos != std::string::npos)
name.erase(pos);
return name;
}
int config::save_2_file(QString file, const void* buf, size_t l)
{
FILE* dst = fopen(file.toStdString().c_str(), "wb");
if(!dst)
return errno;
fwrite(buf, 1, l, dst);
fclose(dst);
return 0;
}
int config::find_config(QString dev_name, std::vector<DEVCFG>& cfgs)
{
std::string name(config::device_to_config_dev_name(dev_name));
int ind = -1;
for(size_t i = 0; i < cfgs.size(); ++i)
{
if(cfgs[i].name == name)
{
ind = i;
break;
}
}
return ind;
}
bool config::is_accessible_file(const std::string& path_file)
{
size_t pos = path_file.rfind('.');
if(pos++ == std::string::npos)
return false;
std::string ext(path_file.substr(pos));
config::to_lower(ext);
return (ext == "png" ||
ext == "jpg" ||
ext == "jpeg" ||
ext == "bmp" ||
ext == "tif" ||
ext == "pdf" ||
ext == "png");
}
void config::to_lower(std::string& str)
{
for(size_t i = 0; i < str.length(); ++i)
{
if(str[i] >= 'A' && str[i] <= 'Z')
str[i] -= 'A' - 'a';
}
}
bool config::load_custom_gamma(const char* file, SANE_Gamma* gamma)
{
bool ret = false;
FILE* src = fopen(file, "rb");
if(src)
{
long l = 0;
SANE_Gamma tmp = {0};
fseek(src, 0, SEEK_END);
l = ftell(src);
fseek(src, 0, SEEK_SET);
if(l == sizeof(SANE_Gamma) &&
fread(&tmp, l, 1, src) == 1)
{
if( tmp.pt_count >= 0 && tmp.pt_count <= sizeof (tmp.keypoint) / sizeof(tmp.keypoint[0]) &&
tmp.pt_count_r >= 0 && tmp.pt_count_r <= sizeof (tmp.keypoint_r) / sizeof(tmp.keypoint_r[0]) &&
tmp.pt_count_g >= 0 && tmp.pt_count_g <= sizeof (tmp.keypoint_g) / sizeof(tmp.keypoint_g[0]) &&
tmp.pt_count_b >= 0 && tmp.pt_count_b <= sizeof (tmp.keypoint_b) / sizeof(tmp.keypoint_b[0]))
{
memcpy(gamma, &tmp, l);
ret = true;
}
}
fclose(src);
}
return ret;
}
int config::load(QString file)
{
if(ini_)
delete ini_;
ini_ = NULL;
if(file.length() == 0)
file = "configs/scanner.conf";
file_ = file;
if(file_[0] != '/')
{
file_ = config::self_path();
file_ += "/" + file;
}
ini_ = new QSettings(file_, QSettings::IniFormat);
ini_->setIniCodec(QTextCodec::codecForName("UTF-8"));
reload_schemes();
return 0;
}
QString config::get_val(QString sec_name, QString key, QString def_val)
{
if(!ini_)
return def_val;
QVariant qv = ini_->value(sec_name + "/" + key);
char buf[128];
if(qv.isNull())
return def_val;
if(qv.type() == QVariant::Type::Int)
{
sprintf(buf, "%d", qv.toInt());
return QString::fromStdString(buf);
}
else if(qv.type() == QVariant::Type::UInt)
{
sprintf(buf, "%u", qv.toInt());
return QString::fromStdString(buf);
}
else if(qv.type() == QVariant::Type::Double)
{
sprintf(buf, "%f", qv.toFloat());
return QString::fromStdString(buf);
}
else
return qv.toString();
}
QString config::get_file(void)
{
return file_;
}
void config::load_all_scanner_configs(std::vector<DEVCFG>& cfgs)
{
#if 0
_opt_scheme opt1;
opt1.name = "aaa";
_opt_scheme opt2;
opt2.name = "bbb";
DEVCFG d1;
d1.name = "d1";
d1.schemes.push_back(opt1);
d1.schemes.push_back(opt2);
cfgs.push_back(d1);
_opt_scheme opt3;
opt3.name = "ccc";
_opt_scheme opt4;
opt4.name = "ddd";
DEVCFG d2;
d2.name = "d2";
d2.schemes.push_back(opt1);
d2.schemes.push_back(opt2);
cfgs.push_back(d2);
#endif
if(!schem_jsn_)
return;
std::vector<std::string> devs;
std::string cont(""), name("");
if(schem_jsn_->first_child(cont, &name))
{
do
{
if(!name.empty())
devs.push_back(name);
}while(schem_jsn_->next_child(cont, &name));
}
for(size_t i = 0; i < devs.size(); ++i)
{
DEVCFG cfg;
load_scanner_configs(QString::fromStdString(devs[i]), &cfg);
cfgs.push_back(cfg);
}
}
void config::load_scanner_configs(QString dev_name, DEVCFG* cfg)
{
std::string name(config::device_to_config_dev_name(dev_name)), cont("");
OPTSCHEME scheme;
OPTVAL val;
cfg->name = name;
cfg->cur_scheme = -1;
if(!schem_jsn_)
return;
gb::json *child = NULL;
schem_jsn_->get_value(name.c_str(), child);
if(!child)
return;
if(child->first_child(cont))
{
gb::json *cur = new gb::json();
if(cur->attach_text(&cont[0]))
{
if(!cur->get_value("cur_sel", cfg->cur_scheme))
cfg->cur_scheme = -1;
}
delete cur;
while(child->next_child(cont))
{
if(cont.empty())
continue;
gb::json jsn, *son = NULL;
if(!jsn.attach_text(&cont[0]))
continue;
jsn.get_value("scheme", scheme.name);
jsn.get_value("opts", son);
if(!son)
continue;
scheme.opts.clear();
if(son->first_child(cont))
{
do
{
if(cont.empty())
continue;
gb::json item;
if(!item.attach_text(&cont[0]))
continue;
if(item.get_value("name", val.name) &&
// item.get_value("type", val.type) &&
item.get_value("value", val.val))
{
item.get_value("extra", val.extra);
scheme.opts.push_back(val);
}
}while(son->next_child(cont));
}
delete son;
if(scheme.opts.size())
cfg->schemes.push_back(scheme);
}
}
delete child;
}
int config::save_scanner_configs(const DEVCFG* cfg)
{
if(!schem_jsn_)
schem_jsn_ = new gb::json();
gb::json *child = NULL, *scheme = NULL, *val = NULL;
std::string text("");
schem_jsn_->get_value(cfg->name.c_str(), child);
if(child)
schem_jsn_->remove(cfg->name.c_str());
if(child)
child->clear();
else {
child = new gb::json();
}
child->create_empty(true);
scheme = new gb::json();
scheme->set_value("cur_sel", cfg->cur_scheme);
child->set_value(NULL, scheme);
delete scheme;
for(size_t i = 0; i < cfg->schemes.size(); ++i)
{
if(cfg->schemes[i].opts.empty())
continue;
scheme = new gb::json();
scheme->create_empty();
scheme->set_value("scheme", cfg->schemes[i].name);
gb::json *opt = new gb::json();
opt->create_empty(true);
for(size_t j = 0; j < cfg->schemes[i].opts.size(); ++j)
{
val = new gb::json();
val->set_value("name", cfg->schemes[i].opts[j].name);
// val->set_value("type", cfg->schemes[i].opts[j].type);
val->set_value("extra", cfg->schemes[i].opts[j].extra);
val->set_value("value", cfg->schemes[i].opts[j].val);
text = val->to_string(false);
opt->set_value(NULL, val);
text = opt->to_string(false);
delete val;
}
printf("scheme %d: %s\n", i + 1, text.c_str());
scheme->set_value("opts", opt);
text = scheme->to_string(false);
printf("all: %s\n", text.c_str());
delete opt;
child->set_value(NULL, scheme);
text = child->to_string(false);
delete scheme;
}
schem_jsn_->set_value(cfg->name.c_str(), child);
delete child;
text = schem_jsn_->to_string(false);
// save as base64
gb::base64 base64;
std::string ec(base64.encode(text.c_str(), text.length()));
return save_2_file(get_scanner_config_file(), ec.c_str(), ec.length());
}