升级配置文件及设备菜单

This commit is contained in:
gb 2022-10-28 09:03:22 +08:00
parent da08031499
commit 99fc6f06a5
17 changed files with 2992 additions and 2847 deletions

View File

@ -1,4 +1,4 @@
/*
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy

View File

@ -1,4 +1,4 @@
/*
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy
@ -20,8 +20,8 @@
THE SOFTWARE.
*/
#ifndef CJSON_H
#define CJSON_H
#ifndef cJSON__h
#define cJSON__h
#include <stdlib.h>
#ifdef __cplusplus

1854
app/scanner/cfg/gb_json.cpp Normal file

File diff suppressed because it is too large Load Diff

232
app/scanner/cfg/gb_json.h Normal file
View File

@ -0,0 +1,232 @@
#pragma once
#if defined(WIN32) || defined(_WIN64)
#include <Windows.h>
#define PATH_SYMBOL "\\"
#else
#define PATH_SYMBOL "/"
#define NULL nullptr
#define DWORD_PTR char*
#define _countof(a) sizeof(a) / sizeof(a[0])
#endif
#include "cJSON.h"
//#include "../../code_device/hgsane/cJSON.h"
#include <vector>
#include <string>
#include <map>
#include <algorithm>
namespace gb
{
class scanner_cfg;
class refer
{
volatile long ref_;
protected:
refer();
virtual ~refer();
public:
long add_ref(void);
long release(void);
};
class json : public refer
{
cJSON *obj_;
cJSON *cur_child_;
cJSON walk_head_;
bool is_array_;
cJSON* find_sibling(cJSON* first, const char* name, cJSON*** addr);
cJSON* find_child(cJSON *parent, std::vector<std::string>& path, bool create, cJSON*** addr = NULL);
cJSON* find(const char* path, bool create = false, cJSON*** addr = NULL);
protected:
~json();
public:
json(char* json_txt = 0);
static std::string to_string(cJSON* root, bool formatted);
static std::string get_value_as_string(cJSON* root, bool integer = false);
static void free_node_data(cJSON* node);
static cJSON* create_element(bool is_array = false);
static cJSON* create_element_with_name(const char* name);
public:
bool attach_text(char* json_txt);
bool attach_cjson(cJSON* cjson);
bool create_empty(bool array = false);
void clear(void);
std::string to_string(bool formatted);
// can be path: child/value ...
bool get_value(const char* key, bool& val);
bool get_value(const char* key, int& val);
bool get_value(const char* key, double& val);
bool get_value(const char* key, std::string& val);
bool get_value(const char* key, json*& val); // caller shoud call "delete" to free the returned object !!!
bool get_value_as_string(const char* key, std::string& val, bool integer);
bool get_as_array(const char* key, std::vector<std::string>& val);
bool first_child(std::string& val, std::string* name = NULL);
bool next_child(std::string& val, std::string* name = NULL);
bool set_value(const char* key, bool val);
bool set_value(const char* key, int val);
bool set_value(const char* key, double val);
bool set_value(const char* key, std::string val);
bool set_value(const char* key, const char* val);
bool set_value(const char* key, json* obj);
bool change_key(const char* old_key, const char* new_key);
bool remove(const char* key);
};
class base64
{
char base64_ind_[128];
char base64_char_[80];
char padding_char_;
bool is_valid_base64_table(const char* table);
bool initialize_base64_table(const char* table);
public:
base64();
~base64();
public:
bool set_base64_table(const char* table = NULL);
std::string encode(const char* data, size_t bytes, unsigned int line_bytes = -1, bool need_padding = true);
std::string decode(const char* data, size_t bytes);
};
class sane_config_schm : public refer
{
std::string scheme_name_;
scanner_cfg *scanner_;
std::string file_;
json* jsn_;
json* bkp_;
json* def_val_;
bool in_setting_;
std::map<int, std::string> id_name_; // (id, default-val)
void clear();
std::string default_value(const char* name);
protected:
~sane_config_schm();
public:
sane_config_schm(scanner_cfg* scanner = nullptr);
static std::string opt_data_appendix_;
static bool hex(unsigned char ch, unsigned char* val);
static bool hex_char(const char* data, unsigned char* val);
static std::string to_hex_letter(const char* data, size_t bytes);
static std::string from_hex_letter(const char* data, size_t bytes);
static bool is_option_data(std::string& name); // reset baase option name into 'name' if name was option data, and return true
public:
sane_config_schm* copy(void);
bool load_from_file(const char* file);
bool load_from_mem(const char* mem, bool in_b64 = true);
bool save_to(const char* file);
void set_default_value(int sn, const char* name, const char* val, size_t bytes);
void copy_default_value(sane_config_schm* from);
bool first_config(std::string& name, std::string& val);
bool next_config(std::string& name, std::string& val);
bool get_config(const char* name, std::string& val);
void begin_setting(bool restore = false);
void config_changed(const char* name, const char* val, size_t bytes, bool extra = false);
void config_changed(int sn, const char* val, size_t bytes, bool extra = false);
void remove_config(const char* name);
void set_value(const char* name, const char* val, size_t bytes, bool extra = false);
bool has_changed(void);
void end_setting(bool cancel);
int id_from_name(const char* name);
std::string to_text_stream(bool b64 = true, bool with_ver = true);
std::string get_version(void);
std::string get_scheme_name(void);
void set_scheme_name(const char* name);
void update(bool(* is_float)(int, void*), void* param, const char*(* t2n)(const char*), std::string* discard = NULL);
};
class scanner_cfg : public refer
{
// format: in base64
//
// {
// "global": {
// "ver": "4.33",
// "cur": -1
// },
// "scheme_1": sane_config_schm*,
// "scheme_2": sane_config_schm*,
// "scheme_3": sane_config_schm*,
// ...
// }
//
std::string path_;
std::string scanner_name_; // scanner type: HUAGOSCAN G100 - 0100
json *global_; // version, current scheme, ...
typedef struct _cfg_schm
{
std::string name;
sane_config_schm* schm;
bool operator==(const char* n)
{
return name == n;
}
}CFGSCHM;
std::vector<CFGSCHM> schemes_;
static std::string global_name_;
static std::string cur_sel_;
static std::string default_setting_name_;
void clear(void);
void init_version(void);
void init_select(void);
void walk_sibling_schemes(cJSON* first);
protected:
~scanner_cfg();
public:
scanner_cfg();
typedef struct _update_func
{
void(* trans_number)(const char* name, std::string& val, void* param);
const char* (* title2name)(const char* title, void* param);
std::string discard_msg; // update failed items ...
void* func_param;
}UDF, *LPUDF;
static bool update(const char* file, LPUDF func);
public:
int load_file(const char* file);
int load_mem(const char* mem);
int save(const char* file = nullptr);
void get_all_schemes(std::vector<std::string>& schemes); // return all schemes name queue, the first is always be 'Default settings'
sane_config_schm* get_scheme(const char* scheme_name = nullptr/*return current scheme if was null*/); // call sane_config_schm::release() if not use anymore
std::string get_current_scheme_name(void);
bool remove_scheme(const char* scheme_name);
void remove_all_schemes(void);
bool select_scheme(const char* scheme_name);
sane_config_schm* copy_scheme(const char* cp_from_name); // for UI setting, call release() if not use anymore
bool add_scheme(sane_config_schm* schm, const char* name = nullptr);
bool rename_scheme(const char* from, const char* to);
};
};

View File

@ -1,626 +0,0 @@
#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>
#include "base/HGUtility.h"
struct
{
const char* name;
const char* title;
}g_opts[] = { {SANE_STD_OPT_NAME_RESTORE , OPTION_TITLE_HFMRSZ}
, {SANE_STD_OPT_NAME_HELP , OPTION_TITLE_BZ}
, {SANE_STD_OPT_NAME_IS_MULTI_OUT , OPTION_TITLE_DLSC}
, {SANE_STD_OPT_NAME_MULTI_OUT_TYPE , OPTION_TITLE_DLSCLX}
, {SANE_STD_OPT_NAME_COLOR_MODE , OPTION_TITLE_YSMS}
, {SANE_STD_OPT_NAME_BINARY_THRESHOLD , OPTION_TITLE_HBTXYZ}
, {SANE_STD_OPT_NAME_REVERSE_01 , OPTION_TITLE_HBTXFSSC}
, {SANE_STD_OPT_NAME_FILTER , OPTION_TITLE_HDHHBTX_CSYZQ}
, {SANE_STD_OPT_NAME_RID_MULTIOUT_RED , OPTION_TITLE_24WCSTX_DLSCCH}
, {SANE_STD_OPT_NAME_RID_ANSWER_SHEET_RED , OPTION_TITLE_24WCSTX_DTKCH}
, {SANE_STD_OPT_NAME_ERASE_BACKGROUND , OPTION_TITLE_BJYC}
, {SANE_STD_OPT_NAME_BKG_COLOR_RANGE , OPTION_TITLE_BJSCFDFW}
, {SANE_STD_OPT_NAME_SHARPEN , OPTION_TITLE_RHYMH}
, {SANE_STD_OPT_NAME_RID_MORR , OPTION_TITLE_QCMW}
, {SANE_STD_OPT_NAME_RID_GRID , OPTION_TITLE_CWW}
, {SANE_STD_OPT_NAME_ERROR_EXTENSION , OPTION_TITLE_CWKS}
, {SANE_STD_OPT_NAME_NOISE_OPTIMIZE , OPTION_TITLE_HBTXZDYH}
, {SANE_STD_OPT_NAME_NOISE_SIZE , OPTION_TITLE_ZDYHCC}
, {SANE_STD_OPT_NAME_PAPER , OPTION_TITLE_ZZCC}
, {SANE_STD_OPT_NAME_CUSTOM_AREA , OPTION_TITLE_ZDYSMQY}
, {SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT , OPTION_TITLE_SMQYZCmm}
, {SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT , OPTION_TITLE_SMQYYCmm}
, {SANE_STD_OPT_NAME_CUSTOM_AREA_TOP , OPTION_TITLE_SMQYSCmm}
, {SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM , OPTION_TITLE_SMQYXCmm}
, {SANE_STD_OPT_NAME_SIZE_CHECK , OPTION_TITLE_CCJC}
, {SANE_STD_OPT_NAME_PAGE , OPTION_TITLE_SMYM}
, {SANE_STD_OPT_NAME_DISCARD_BLANK_SENS , OPTION_TITLE_TGKBYLMD}
, {SANE_STD_OPT_NAME_RESOLUTION , OPTION_TITLE_FBL}
, {SANE_STD_OPT_NAME_TIME_TO_SLEEP , OPTION_TITLE_XMSJ}
, {SANE_STD_OPT_NAME_IMAGE_QUALITY , OPTION_TITLE_HZ}
, {SANE_STD_OPT_NAME_EXCHANGE ,OPTION_TITLE_JHZFM}
, {SANE_STD_OPT_NAME_SPLIT ,OPTION_TITLE_TXCF }
, {SANE_STD_OPT_NAME_ANTI_SKEW , OPTION_TITLE_ZDJP}
, {SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA , OPTION_TITLE_QYSDQX}
, {SANE_STD_OPT_NAME_GAMMA , OPTION_TITLE_JMZ}
, {SANE_STD_OPT_NAME_BRIGHTNESS , OPTION_TITLE_LDZ}
, {SANE_STD_OPT_NAME_CONTRAST , OPTION_TITLE_DBD}
, {SANE_STD_OPT_NAME_IS_PHOTO_MODE , OPTION_TITLE_ZPMS}
, {SANE_STD_OPT_NAME_ERASE_BLACK_FRAME , OPTION_TITLE_XCHK}
, {SANE_STD_OPT_NAME_DARK_SAMPLE , OPTION_TITLE_SSYZ}
, {SANE_STD_OPT_NAME_THRESHOLD , OPTION_TITLE_YZ}
, {SANE_STD_OPT_NAME_ANTI_NOISE_LEVEL , OPTION_TITLE_BJKZDJ}
, {SANE_STD_OPT_NAME_MARGIN , OPTION_TITLE_BYSJ}
, {SANE_STD_OPT_NAME_FILL_BKG_MODE , OPTION_TITLE_BJTCFS}
, {SANE_STD_OPT_NAME_IS_ANTI_PERMEATE , OPTION_TITLE_FZST}
, {SANE_STD_OPT_NAME_ANTI_PERMEATE_LEVEL , OPTION_TITLE_FZSTDJ}
, {SANE_STD_OPT_NAME_RID_HOLE_L , OPTION_TITLE_CKYCZC}
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_L , OPTION_TITLE_ZCCKSSFWZFMBL}
, {SANE_STD_OPT_NAME_RID_HOLE_R , OPTION_TITLE_CKYCYC}
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_R , OPTION_TITLE_YCCKSSFWZFMBL}
, {SANE_STD_OPT_NAME_RID_HOLE_T , OPTION_TITLE_CKYCSC}
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_T , OPTION_TITLE_SCCKSSFWZFMBL}
, {SANE_STD_OPT_NAME_RID_HOLE_B , OPTION_TITLE_CKYCXC}
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_B , OPTION_TITLE_XCCKSSFWZFMBL}
, {SANE_STD_OPT_NAME_IS_FILL_COLOR , OPTION_TITLE_SCTC}
, {SANE_STD_OPT_NAME_IS_ULTROSONIC_CHECK , OPTION_TITLE_CSBJC}
, {SANE_STD_OPT_NAME_DOUBLE_FEED_HANDLE , OPTION_TITLE_SZTPCL}
, {SANE_STD_OPT_NAME_IS_CHECK_STAPLE , OPTION_TITLE_ZDJC}
, {SANE_STD_OPT_NAME_SCAN_MODE , OPTION_TITLE_SMZS}
, {SANE_STD_OPT_NAME_SCAN_COUNT , OPTION_TITLE_SMSL}
, {SANE_STD_OPT_NAME_TEXT_DIRECTION , OPTION_TITLE_WGFX}
, {SANE_STD_OPT_NAME_IS_ROTATE_BKG_180 , OPTION_TITLE_BMXZ180}
, {SANE_STD_OPT_NAME_IS_CHECK_DOG_EAR , OPTION_TITLE_ZJJC}
, {SANE_STD_OPT_NAME_DOG_EAR_SIZE , OPTION_TITLE_ZJDX}
, {SANE_STD_OPT_NAME_IS_CHECK_ASKEW , OPTION_TITLE_WXJC}
, {SANE_STD_OPT_NAME_ASKEW_RANGE , OPTION_TITLE_WXRRD}
, {SANE_STD_OPT_NAME_FEED_STRENGTH , OPTION_TITLE_FZQD}
, {SANE_STD_OPT_NAME_IS_AUTO_FEED_STRENGTH , OPTION_TITLE_ZDFZQD}
, {SANE_STD_OPT_NAME_FEED_STRENGTH_VALUE , OPTION_TITLE_JZSBL}
, {SANE_STD_OPT_NAME_WAIT_TO_SCAN , OPTION_TITLE_DZSM}
},
g_discard[] = { {SANE_STD_OPT_NAME_REVERSE_01 , "\351\273\221\347\231\275\345\233\276\345\203\217\345\217\215\350\211\262\350\276\223\345\207\272\357\274\210\346\255\243\345\270\270\351\242\234\350\211\262\344\270\272\357\274\2320-\351\273\221\350\211\262\357\274\2331-\347\231\275\350\211\262\357\274\211"} // 黑白图像反色输出正常颜色为0-黑色1-白色)
, {SANE_STD_OPT_NAME_FILTER , "\347\201\260\345\272\246\346\210\226\351\273\221\347\231\275\345\233\276\345\203\217 - \351\231\244\350\211\262"} // 灰度或黑白图像 - 除色
, {SANE_STD_OPT_NAME_IS_AUTO_FEED_STRENGTH , "\350\207\252\345\212\250\346\220\223\347\272\270\345\274\272\345\272\246"} // 自动搓纸强度
, {SANE_STD_OPT_NAME_FEED_STRENGTH_VALUE , "\346\220\223\347\272\270\351\230\210\345\200\274"} // " 搓纸阈值"
};
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)
{
HGChar logpath[512] = {0};
HGBase_GetConfigPath(logpath, 512);
file = strcat(logpath, "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)
{
pos = name.find(" - ", pos + 3); // the first is ' - PID' 2022-10-11
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 = dev_name.toStdString();
int ind = -1;
for(size_t i = 0; i < cfgs.size(); ++i)
{
if(cfgs[i].m_originDeviceName == 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 = "scanner.conf";
file_ = file;
if(file_[0] != '/')
{
HGChar logpath[512] = {0};
HGBase_GetConfigPath(logpath, sizeof(logpath) / sizeof(logpath[0]) - 1);
file_ = logpath;
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::transferTitle2Name(std::string& name)
{
int size = sizeof(g_opts) / sizeof(g_opts[0]);
for (size_t i = 0; i < size; i++)
{
if (strcmp(name.c_str(), g_opts[i].title) == 0)
{
name = g_opts[i].name;
}
}
}
std::string config::transferName2Title(std::string& name)
{
int size = sizeof(g_opts) / sizeof(g_opts[0]);
for (size_t i = 0; i < size; i++)
{
if (strcmp(name.c_str(), g_opts[i].name) == 0)
{
name = g_opts[i].title;
}
}
return name;
}
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->m_deviceName = 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.m_schemeTitle);
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("value", val.val))
{
transferTitle2Name(val.name); // chinese title to english name
item.get_value("title", val.title);
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->m_deviceName.c_str(), child);
if(child)
schem_jsn_->remove(cfg->m_deviceName.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);
scheme->set_value("version", cfg->appVersionNum);
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].m_schemeTitle);
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("title", cfg->schemes[i].opts[j].title);
// 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->m_deviceName.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());
}

View File

@ -1,162 +0,0 @@
#pragma once
#include <vector>
#include <string>
#include <qsettings.h>
#include <algorithm>
#include <math.h>
#include "sane/sane_ex.h"
#include "sane/sane_option_definitions.h"
#include "json.h"
#define IS_DOUBLE_EQUAL(a, b) fabs((a) - (b)) < .00001
typedef struct _opt_val
{
std::string name;
std::string title;
std::string type;
std::string val;
std::string extra;
bool operator==(const struct _opt_val& r)
{
if(name != r.name)
return false;
if(type == "float")
{
return IS_DOUBLE_EQUAL(atof(val.c_str()), atof(r.val.c_str()));
}
else {
return val == r.val && extra == r.extra;
}
}
bool operator==(const std::string& n)
{
return name == n;
}
}OPTVAL;
typedef struct _opt_scheme
{
std::string m_schemeName; // scheme name
std::string m_schemeTitle; //shcheme title
std::vector<OPTVAL> opts;
bool operator==(const std::string& n)
{
return m_schemeName == n;
}
bool operator==(const struct _opt_scheme& r)
{
if(opts.size() != r.opts.size())
return false;
bool equal = true;
for(size_t i = 0; i < r.opts.size(); ++i)
{
std::vector<OPTVAL>::iterator it = std::find(opts.begin(), opts.end(), r.opts[i].name);
if(it == opts.end() ||
r.opts[i].val != it->val)
{
equal = false;
break;
}
}
return equal;
}
}OPTSCHEME;
typedef struct _dev_configs
{
std::string m_deviceName; // device name
std::string m_originDeviceName; //If the model of the second device is the same, remember the original name of the second device
int cur_scheme; // -1 is none user scheme applied, and points to the default setting which at first in 'schemes'
std::string appVersionNum;
std::vector<OPTSCHEME> schemes; // NOTE: the first is always the default setting, and (cur_scheme + 1) is the user customizing setting, -1 is the default setting
bool operator==(const std::string& n)
{
return m_deviceName == n;
}
_dev_configs()
{
OPTSCHEME none;
none.m_schemeName = "\351\273\230\350\256\244\350\256\276\347\275\256"; // "默认设置";
schemes.push_back(none);
cur_scheme = -1;
}
OPTSCHEME* get_current(void)
{
if(cur_scheme >= 0 && cur_scheme + 1 < (int)schemes.size())
return &schemes[cur_scheme + 1];
else
return nullptr;
}
OPTSCHEME* select(const std::string& name)
{
std::vector<OPTSCHEME>::iterator it = std::find(schemes.begin(), schemes.end(), name);
if(it == schemes.end())
return nullptr;
cur_scheme = it - schemes.begin() - 1;
return &(*it);
}
}DEVCFG;
//
// {
// "G100" : [
// {
// "scheme": "color-A4R",
// "opts": [
// {
// "name": "color-mode",
// "type": "string",
// "value": "24-bits",
// "init": "24-bits"
// },
// {
// "name": "paper",
// "type": "string",
// "value": "A4R"
// "init": "A4"
// }],
// }],
//
// "G200" : [ ... ]
//
// }
//
class config
{
QSettings *ini_;
QString file_;
gb::json *schem_jsn_;
QString get_scanner_config_file(void);
void reload_schemes(void);
public:
config();
~config();
static QString self_path(void); // without last '/'
static std::string read_mini_file(QString file);
static std::string device_to_config_dev_name(QString& dev_name);
static int save_2_file(QString file, const void* buf, size_t l);
static int find_config(QString dev_name, std::vector<DEVCFG>& cfgs);
static bool is_accessible_file(const std::string& path_file);
static void to_lower(std::string& str);
static bool load_custom_gamma(const char* file, SANE_Gamma* gamma);
public:
int load(QString file = "");
QString get_val(QString sec_name, QString key, QString def_val = "");
QString get_file(void);
void load_all_scanner_configs(std::vector<DEVCFG>& cfgs);
void load_scanner_configs(QString dev_name, DEVCFG* cfg);
int save_scanner_configs(const DEVCFG* cfg);
void transferTitle2Name(std::string& name);
std::string transferName2Title(std::string& name);
};

View File

@ -7,7 +7,7 @@ device_menu::device_menu(QWidget *parent)
, cur_action_(nullptr), none_action_(nullptr)
{
group_action_ = new QActionGroup(this);
deviceMenuUpdate(nullptr, "");
deviceMenuUpdate(nullptr);
connect(group_action_, SIGNAL(triggered(QAction*)), this, SLOT(on_act_triggered(QAction*)));
}
@ -16,7 +16,7 @@ device_menu::device_menu(const QString &title, QWidget *parent)
, cur_action_(nullptr), none_action_(nullptr)
{
group_action_ = new QActionGroup(this);
deviceMenuUpdate(nullptr, "");
deviceMenuUpdate(nullptr);
connect(group_action_, SIGNAL(triggered(QAction*)), this, SLOT(on_act_triggered(QAction*)));
}
@ -91,7 +91,7 @@ void device_menu::get_online_devices(QList<QString>& dev_names)
}
}
void device_menu::deviceMenuUpdate(const std::vector<DEVCFG>* dev_cfgs, std::string curDeviceName)
void device_menu::deviceMenuUpdate(dev_que* que)
{
std::lock_guard<std::mutex> lock(mutex_);
if(none_action_)
@ -102,7 +102,7 @@ void device_menu::deviceMenuUpdate(const std::vector<DEVCFG>* dev_cfgs, std::str
for(size_t i = 0; i < menus_.size(); ++i)
menus_[i].menu->setEnabled(false);
if (!dev_cfgs || dev_cfgs->empty())
if (!que || que->scanners() == 0)
{
if(menus_.empty())
{
@ -113,13 +113,15 @@ void device_menu::deviceMenuUpdate(const std::vector<DEVCFG>* dev_cfgs, std::str
return;
}
for (size_t i = 0; i < dev_cfgs->size(); i++)
for (size_t i = 0; i < que->scanners(); i++)
{
std::vector<POPMENU>::iterator it = std::find(menus_.begin(), menus_.end(), QString::fromStdString((*dev_cfgs)[i].m_originDeviceName));
SCANNER s = que->get_at(i);
std::vector<POPMENU>::iterator it = std::find(menus_.begin(), menus_.end(), QString::fromStdString((s.name)));
POPMENU pm;
std::vector<std::string> schemes;
if(it == menus_.end())
pm.menu = addMenu(QString::fromStdString((*dev_cfgs)[i].m_originDeviceName));
pm.menu = addMenu(QString::fromStdString(s.name));
else
{
pm = *it;
@ -133,43 +135,29 @@ void device_menu::deviceMenuUpdate(const std::vector<DEVCFG>* dev_cfgs, std::str
group_action_->removeAction(pm.actions[j]);
}
pm.actions.clear();
for (size_t j = 0; j < (*dev_cfgs)[i].schemes.size(); j++)
s.cfg->get_all_schemes(schemes);
for (size_t j = 0; j < schemes.size(); j++)
{
QAction *child;
if(!(*dev_cfgs)[i].schemes[j].m_schemeTitle.empty())
child = group_action_->addAction(QString::fromStdString((*dev_cfgs)[i].schemes[j].m_schemeTitle));
else
child = group_action_->addAction(QString::fromStdString((*dev_cfgs)[i].schemes[j].m_schemeName));
child->setProperty(ACTION_DEVICE_NAME_PROPERTY, QVariant(QString::fromStdString((*dev_cfgs)[i].m_originDeviceName)));
QAction *child = group_action_->addAction(QString::fromStdString(schemes[j]));
child->setProperty(ACTION_DEVICE_NAME_PROPERTY, QVariant(QString::fromStdString(s.name)));
child->setCheckable(true);
if((*dev_cfgs)[i].cur_scheme == -1)
{
if(child->text().toStdString() == (*dev_cfgs)[i].schemes[j].m_schemeName)
child->setChecked(true);
}
else
if(que->opened_scanner_name() == s.name &&
schemes[j] == s.cfg->get_current_scheme_name())
child->setChecked(true);
pm.menu->addAction(child);
pm.actions.push_back(child);
const std::vector<OPTVAL>& opts = (*dev_cfgs)[i].schemes[j].opts;
QString tips;
for(size_t k = 0; k < opts.size(); ++k)
{
if(!opts[k].title.empty())
tips += QString::fromStdString(opts[k].title + ": " + opts[k].val + "\n");
else
tips += QString::fromStdString(opts[k].name + ": " + opts[k].val + "\n");
}
if(tips.isNull())
{
tips = tr("default setting");
}
child->setToolTip(tips);
// child->setToolTip(tips);
}
menus_.push_back(pm);
s.cfg->release();
}
}

View File

@ -2,10 +2,462 @@
#define DEVICE_MENU_H
#include <QMenu>
#include "config.h"
#include <mutex>
#include "sane/sane_ex.h"
#include "sane/sane_option_definitions.h"
#include "../../../sdk/include/huagao/hgscanner_error.h"
#include "cfg/gb_json.h"
typedef struct _scanner
{
std::string name;
std::string model;
bool online;
gb::scanner_cfg *cfg;
}SCANNER;
class dev_que
{
std::vector<SCANNER> que_;
std::string root_dir_;
std::string opened_scanner_;
std::string applied_scheme_;
SANE_Handle handle_;
static void trans_number(const char* name, std::string& val, void* param)
{
if (strcmp(name, "tl-x") == 0
|| strcmp(name, "br-x") == 0
|| strcmp(name, "tl-y") == 0
|| strcmp(name, "br-y") == 0
|| strcmp(name, "gamma") == 0
|| strcmp(name, "search-hole-range-l") == 0
|| strcmp(name, "search-hole-range-r") == 0
|| strcmp(name, "search-hole-range-t") == 0
|| strcmp(name, "search-hole-range-b") == 0
|| strcmp(name, "feed-strength-value") == 0
)
{
float v = atof(val.c_str());
SANE_Fixed f = SANE_FIX(v);
val = std::string((char*)&f, sizeof(f));
}
else if (strcmp(name, "binary-threshold") == 0
|| strcmp(name, "bkg-color-range") == 0
|| strcmp(name, "noise-size") == 0
|| strcmp(name, "blank-sensitivity") == 0
|| strcmp(name, "resolution") == 0
|| strcmp(name, "brightness") == 0
|| strcmp(name, "contrast") == 0
|| strcmp(name, "threshold") == 0
|| strcmp(name, "anti-noise-level") == 0
|| strcmp(name, "margin") == 0
|| strcmp(name, "scan-count") == 0
|| strcmp(name, "askew-range") == 0
|| strcmp(name, "dog-ear-size") == 0
)
{
SANE_Int v = atoi(val.c_str());
val = std::string((char*)&v, sizeof(v));
}
else if (strcmp(val.c_str(), "true") == 0)
{
SANE_Bool b = SANE_TRUE;
val = std::string((char*)&b, sizeof(b));
}
else if (strcmp(val.c_str(), "false") == 0)
{
SANE_Bool b = SANE_FALSE;
val = std::string((char*)&b, sizeof(b));
}
}
static const char* title_2_name(const char* title, void* param)
{
struct
{
const char* name;
const char* title;
}g_opts[] = { {SANE_STD_OPT_NAME_RESTORE , OPTION_TITLE_HFMRSZ}
, {SANE_STD_OPT_NAME_HELP , OPTION_TITLE_BZ}
, {SANE_STD_OPT_NAME_IS_MULTI_OUT , OPTION_TITLE_DLSC}
, {SANE_STD_OPT_NAME_MULTI_OUT_TYPE , OPTION_TITLE_DLSCLX}
, {SANE_STD_OPT_NAME_COLOR_MODE , OPTION_TITLE_YSMS}
, {SANE_STD_OPT_NAME_BINARY_THRESHOLD , OPTION_TITLE_HBTXYZ}
, {SANE_STD_OPT_NAME_REVERSE_01 , OPTION_TITLE_HBTXFSSC}
, {SANE_STD_OPT_NAME_FILTER , OPTION_TITLE_HDHHBTX_CSYZQ}
, {SANE_STD_OPT_NAME_RID_MULTIOUT_RED , OPTION_TITLE_24WCSTX_DLSCCH}
, {SANE_STD_OPT_NAME_RID_ANSWER_SHEET_RED , OPTION_TITLE_24WCSTX_DTKCH}
, {SANE_STD_OPT_NAME_ERASE_BACKGROUND , OPTION_TITLE_BJYC}
, {SANE_STD_OPT_NAME_BKG_COLOR_RANGE , OPTION_TITLE_BJSCFDFW}
, {SANE_STD_OPT_NAME_SHARPEN , OPTION_TITLE_RHYMH}
, {SANE_STD_OPT_NAME_RID_MORR , OPTION_TITLE_QCMW}
, {SANE_STD_OPT_NAME_RID_GRID , OPTION_TITLE_CWW}
, {SANE_STD_OPT_NAME_ERROR_EXTENSION , OPTION_TITLE_CWKS}
, {SANE_STD_OPT_NAME_NOISE_OPTIMIZE , OPTION_TITLE_HBTXZDYH}
, {SANE_STD_OPT_NAME_NOISE_SIZE , OPTION_TITLE_ZDYHCC}
, {SANE_STD_OPT_NAME_PAPER , OPTION_TITLE_ZZCC}
, {SANE_STD_OPT_NAME_CUSTOM_AREA , OPTION_TITLE_ZDYSMQY}
, {SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT , OPTION_TITLE_SMQYZCmm}
, {SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT , OPTION_TITLE_SMQYYCmm}
, {SANE_STD_OPT_NAME_CUSTOM_AREA_TOP , OPTION_TITLE_SMQYSCmm}
, {SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM , OPTION_TITLE_SMQYXCmm}
, {SANE_STD_OPT_NAME_SIZE_CHECK , OPTION_TITLE_CCJC}
, {SANE_STD_OPT_NAME_PAGE , OPTION_TITLE_SMYM}
, {SANE_STD_OPT_NAME_DISCARD_BLANK_SENS , OPTION_TITLE_TGKBYLMD}
, {SANE_STD_OPT_NAME_RESOLUTION , OPTION_TITLE_FBL}
, {SANE_STD_OPT_NAME_TIME_TO_SLEEP , OPTION_TITLE_XMSJ}
, {SANE_STD_OPT_NAME_IMAGE_QUALITY , OPTION_TITLE_HZ}
, {SANE_STD_OPT_NAME_EXCHANGE ,OPTION_TITLE_JHZFM}
, {SANE_STD_OPT_NAME_SPLIT ,OPTION_TITLE_TXCF }
, {SANE_STD_OPT_NAME_ANTI_SKEW , OPTION_TITLE_ZDJP}
, {SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA , OPTION_TITLE_QYSDQX}
, {SANE_STD_OPT_NAME_GAMMA , OPTION_TITLE_JMZ}
, {SANE_STD_OPT_NAME_BRIGHTNESS , OPTION_TITLE_LDZ}
, {SANE_STD_OPT_NAME_CONTRAST , OPTION_TITLE_DBD}
, {SANE_STD_OPT_NAME_IS_PHOTO_MODE , OPTION_TITLE_ZPMS}
, {SANE_STD_OPT_NAME_ERASE_BLACK_FRAME , OPTION_TITLE_XCHK}
, {SANE_STD_OPT_NAME_DARK_SAMPLE , OPTION_TITLE_SSYZ}
, {SANE_STD_OPT_NAME_THRESHOLD , OPTION_TITLE_YZ}
, {SANE_STD_OPT_NAME_ANTI_NOISE_LEVEL , OPTION_TITLE_BJKZDJ}
, {SANE_STD_OPT_NAME_MARGIN , OPTION_TITLE_BYSJ}
, {SANE_STD_OPT_NAME_FILL_BKG_MODE , OPTION_TITLE_BJTCFS}
, {SANE_STD_OPT_NAME_IS_ANTI_PERMEATE , OPTION_TITLE_FZST}
, {SANE_STD_OPT_NAME_ANTI_PERMEATE_LEVEL , OPTION_TITLE_FZSTDJ}
, {SANE_STD_OPT_NAME_RID_HOLE_L , OPTION_TITLE_CKYCZC}
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_L , OPTION_TITLE_ZCCKSSFWZFMBL}
, {SANE_STD_OPT_NAME_RID_HOLE_R , OPTION_TITLE_CKYCYC}
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_R , OPTION_TITLE_YCCKSSFWZFMBL}
, {SANE_STD_OPT_NAME_RID_HOLE_T , OPTION_TITLE_CKYCSC}
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_T , OPTION_TITLE_SCCKSSFWZFMBL}
, {SANE_STD_OPT_NAME_RID_HOLE_B , OPTION_TITLE_CKYCXC}
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_B , OPTION_TITLE_XCCKSSFWZFMBL}
, {SANE_STD_OPT_NAME_IS_FILL_COLOR , OPTION_TITLE_SCTC}
, {SANE_STD_OPT_NAME_IS_ULTROSONIC_CHECK , OPTION_TITLE_CSBJC}
, {SANE_STD_OPT_NAME_DOUBLE_FEED_HANDLE , OPTION_TITLE_SZTPCL}
, {SANE_STD_OPT_NAME_IS_CHECK_STAPLE , OPTION_TITLE_ZDJC}
, {SANE_STD_OPT_NAME_SCAN_MODE , OPTION_TITLE_SMZS}
, {SANE_STD_OPT_NAME_SCAN_COUNT , OPTION_TITLE_SMSL}
, {SANE_STD_OPT_NAME_TEXT_DIRECTION , OPTION_TITLE_WGFX}
, {SANE_STD_OPT_NAME_IS_ROTATE_BKG_180 , OPTION_TITLE_BMXZ180}
, {SANE_STD_OPT_NAME_IS_CHECK_DOG_EAR , OPTION_TITLE_ZJJC}
, {SANE_STD_OPT_NAME_DOG_EAR_SIZE , OPTION_TITLE_ZJDX}
, {SANE_STD_OPT_NAME_IS_CHECK_ASKEW , OPTION_TITLE_WXJC}
, {SANE_STD_OPT_NAME_ASKEW_RANGE , OPTION_TITLE_WXRRD}
, {SANE_STD_OPT_NAME_FEED_STRENGTH , OPTION_TITLE_FZQD}
, {SANE_STD_OPT_NAME_IS_AUTO_FEED_STRENGTH , OPTION_TITLE_ZDFZQD}
, {SANE_STD_OPT_NAME_FEED_STRENGTH_VALUE , OPTION_TITLE_JZSBL}
, {SANE_STD_OPT_NAME_WAIT_TO_SCAN , OPTION_TITLE_DZSM}
, {SANE_STD_OPT_NAME_FOLD_TYPE , OPTION_TITLE_DZMS}
},
g_discard[] = { {SANE_STD_OPT_NAME_REVERSE_01 , "\351\273\221\347\231\275\345\233\276\345\203\217\345\217\215\350\211\262\350\276\223\345\207\272\357\274\210\346\255\243\345\270\270\351\242\234\350\211\262\344\270\272\357\274\2320-\351\273\221\350\211\262\357\274\2331-\347\231\275\350\211\262\357\274\211"} // 黑白图像反色输出正常颜色为0-黑色1-白色)
, {SANE_STD_OPT_NAME_FILTER , "\347\201\260\345\272\246\346\210\226\351\273\221\347\231\275\345\233\276\345\203\217 - \351\231\244\350\211\262"} // 灰度或黑白图像 - 除色
, {SANE_STD_OPT_NAME_IS_AUTO_FEED_STRENGTH , "\350\207\252\345\212\250\346\220\223\347\272\270\345\274\272\345\272\246"} // 自动搓纸强度
, {SANE_STD_OPT_NAME_FEED_STRENGTH_VALUE , "\346\220\223\347\272\270\351\230\210\345\200\274"} // " 搓纸阈值"
};
while (*title == ' ')
title++;
for (size_t i = 0; i < _countof(g_opts); ++i)
{
if (strcmp(title, g_opts[i].title) == 0)
return g_opts[i].name;
}
for (size_t i = 0; i < _countof(g_discard); ++i)
{
if (strcmp(title, g_discard[i].title) == 0)
return g_discard[i].name;
}
return title;
}
public:
dev_que() : handle_(nullptr)
{}
~dev_que()
{
close_scanner();
for(auto& v : que_)
v.cfg->release();
}
static void update_old_cfg(const char* conf)
{
gb::scanner_cfg::UDF func;
func.func_param = nullptr;
func.title2name = &dev_que::title_2_name;
func.trans_number = &dev_que::trans_number;
gb::scanner_cfg::update(conf, &func);
}
static void apply_scheme(SANE_Handle h, gb::sane_config_schm* schm)
{
SANE_Int count = 0, none = 0;
std::string name(""), val("");
none = sane_io_control(h, IO_CTRL_CODE_RESTORE_SETTINGS, NULL, NULL);
if(schm && schm->id_from_name(SANE_STD_OPT_NAME_COLOR_MODE) == -1)
{
SANE_Int dev_options = 0;
sane_control_option(h, 0, SANE_ACTION_GET_VALUE, &dev_options, nullptr);
for(int i = 1; i < dev_options; ++i)
{
const SANE_Option_Descriptor* opt = sane_get_option_descriptor(h, i);
if(!opt)
continue;
unsigned int n = i;
if(opt->type == SANE_TYPE_BOOL)
{
SANE_Bool v = SANE_TRUE;
sane_io_control(h, IO_CTRL_CODE_GET_DEFAULT_VALUE, &v, &n);
schm->set_default_value(i, opt->name, (char*)&v, sizeof(v));
}
else if (opt->type == SANE_TYPE_INT) {
SANE_Int v = 0;
sane_io_control(h, IO_CTRL_CODE_GET_DEFAULT_VALUE, &v, &n);
schm->set_default_value(i, opt->name, (char*)&v, sizeof(v));
}
else if(opt->type == SANE_TYPE_FIXED)
{
SANE_Fixed v = 0;
sane_io_control(h, IO_CTRL_CODE_GET_DEFAULT_VALUE, &v, &n);
schm->set_default_value(i, opt->name, (char*)&v, sizeof(v));
}
else {
char *buf = new char[opt->size + 4];
memset(buf, 0, opt->size + 4);
sane_io_control(h, IO_CTRL_CODE_GET_DEFAULT_VALUE, buf, &n);
schm->set_default_value(i, opt->name, buf, strlen(buf));
delete[] buf;
}
}
}
if(schm && schm->first_config(name, val))
{
do
{
int id = schm->id_from_name(name.c_str());
if(id == -1)
{
if(gb::sane_config_schm::is_option_data(name))
{
if(name == SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA && val.length() == sizeof(SANE_Gamma))
{
unsigned int l = val.length();
sane_io_control(h, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &val[0], &l);
}
}
}
else {
const SANE_Option_Descriptor* opt = reinterpret_cast<const SANE_Option_Descriptor*>(sane_get_option_descriptor(h, id));
if(opt)
{
if(opt->type == SANE_TYPE_STRING)
{
char *buf = new char[opt->size + 4];
memset(buf, 0, opt->size + 4);
strcpy(buf, val.c_str());
sane_control_option(h, id, SANE_ACTION_SET_VALUE, buf, &none);
delete[] buf;
}
else {
sane_control_option(h, id, SANE_ACTION_SET_VALUE, &val[0], &none);
}
}
}
}while(schm->next_config(name, val));
}
}
public:
void set_root_dir(const char* root)
{
root_dir_ = std::string(root) + PATH_SYMBOL;
}
void add_scanner(const char* sane_name)
{
bool found = false;
for(auto& v: que_)
{
if(v.name == sane_name)
{
found = true;
break;
}
}
if(!found)
{
SCANNER s;
size_t pos = 0;
s.model = s.name = sane_name;
s.cfg = nullptr;
pos = s.model.find(" - ");
if(pos != std::string::npos)
{
pos = s.model.find(" - ", pos + 3);
if(pos != std::string::npos)
s.model.erase(pos);
}
for(auto& v: que_)
{
if(v.model == s.model)
{
s.cfg = v.cfg;
s.cfg->add_ref();
break;
}
}
if(!s.cfg)
{
s.cfg = new gb::scanner_cfg();
s.cfg->load_file((root_dir_ + s.model + ".cfg").c_str());
}
s.online = true;
que_.push_back(s);
}
}
void get_schemes(const char* scanner_name, std::vector<std::string>& schemes)
{
schemes.clear();
for(auto& v : que_)
{
if(v.name == scanner_name)
{
v.cfg->get_all_schemes(schemes);
break;
}
}
}
SANE_Handle handle(void)
{
return handle_;
}
std::string opened_scanner_name(void)
{
return opened_scanner_;
}
std::string applied_scheme(void)
{
return applied_scheme_;
}
int open_scanner(const char* scanner_name, const char* scheme = nullptr)
{
SANE_Status statu = SANE_STATUS_GOOD;
close_scanner();
statu = sane_open(scanner_name, &handle_);
if(statu == SANE_STATUS_GOOD && handle_)
{
opened_scanner_ = scanner_name;
apply_scheme(scheme);
}
}
int close_scanner(void)
{
if(handle_)
{
sane_close(handle_);
handle_ = nullptr;
opened_scanner_ = "";
applied_scheme_ = "";
}
return SANE_STATUS_GOOD;
}
int scanners(void)
{
return que_.size();
}
SCANNER get_at(int pos)
{
SCANNER s;
s.name = s.model = "";
s.cfg = nullptr;
if(pos >= 0 && pos < que_.size())
{
s = que_[pos];
s.cfg->add_ref();
}
return s;
}
bool is_online(const char* scanner = nullptr)
{
if(!scanner)
scanner = opened_scanner_.c_str();
for(auto& v : que_)
{
if(v.name == scanner)
return v.online;
}
return false;
}
void set_online(bool online, const char* scanner = nullptr)
{
if(!scanner)
scanner = opened_scanner_.c_str();
for(auto& v : que_)
{
if(v.name == scanner)
{
v.online = online;
break;
}
}
}
void get_scanners(std::vector<std::string>& que)
{
for(auto& v: que_)
que.push_back(v.name);
}
int apply_scheme(const char* scheme_name)
{
if(!handle_)
return SCANNER_ERR_NOT_OPEN;
for(auto& v: que_)
{
if(v.name == opened_scanner_)
{
gb::sane_config_schm* schm = v.cfg->get_scheme(scheme_name);
dev_que::apply_scheme(handle_, schm);
if(schm)
{
v.cfg->select_scheme(schm->get_scheme_name().c_str());
schm->release();
}
else {
v.cfg->select_scheme(scheme_name);
}
applied_scheme_ = scheme_name ? scheme_name : "";
if(applied_scheme_.empty())
{
std::vector<std::string> all;
v.cfg->get_all_schemes(all);
applied_scheme_ = all[0];
}
v.cfg->save();
break;
}
}
}
};
Q_DECLARE_METATYPE(OPTSCHEME)
class device_menu : public QMenu
{
@ -33,7 +485,7 @@ public:
device_menu(QWidget* parent = nullptr);
device_menu(const QString& title, QWidget* parent = nullptr);
void deviceMenuUpdate(const std::vector<DEVCFG>* dev_cfgs, std::string curDeviceName);
void deviceMenuUpdate(dev_que* que);
void connectedDevice(const QString& device);

File diff suppressed because it is too large Load Diff

View File

@ -5,36 +5,22 @@
#include <QSettings>
#include <algorithm>
#include "sane/sane_ex.h"
#include "config.h"
#include "cfg/gb_json.h"
#include "device_menu.h"
class hg_settingdialog : public QDialog
{
Q_OBJECT
DEVCFG* schemes_;
int cur_ind_; // [0, scheme size - 2] will be replaced when click 'OK' button, if want to add new item, set it to -1; add ONE on it when accept source
typedef struct _changed_opt
{
int opt;
QVariant val;
bool operator==(const int& ind)
{
return opt == ind;
}
}CHANGEDOPT;
std::vector<CHANGEDOPT> default_vals_; // values which changed
std::vector<CHANGEDOPT> init_vals_; // values when initialize controls
std::vector<CHANGEDOPT> changed_opts_; // values which changed
int changed_count_;
bool save_;
bool clicked_gamma_;
config* cfg_file_;
dev_que *dev_que_;
gb::scanner_cfg *cur_cfg_;
gb::sane_config_schm *cur_scheme_;
void refresh_control_value(int op_id);
bool is_covered(std::vector<OPTVAL>& org, std::vector<OPTVAL>& now); // if all options in org are inclued in now, then return true
void on_select_scheme(int scheme_ind, bool apply_to_dev = true);
void on_select_scheme(bool apply_to_dev = true);
QString gen_gamma_file_path(void);
QMenu *top_menu_;
@ -60,7 +46,7 @@ class hg_settingdialog : public QDialog
public:
explicit hg_settingdialog(void *handle, QWidget *parent = nullptr,
DEVCFG* cfg = nullptr);
dev_que* dev = nullptr);
~hg_settingdialog();
public:
@ -71,7 +57,6 @@ public:
QVector<QWidget*> find_control(int opt_num);
void keyPressEvent(QKeyEvent *e);
int get_changed_items(void);
void set_config_file(config* cfg);
private:
void *m_handle;
@ -88,18 +73,12 @@ private:
const void* find_option_description(int id); // return const SANE_Option_Descriptor* pointer
const void* find_option_description(const std::string& title, int* id); // return const SANE_Option_Descriptor* pointer
QVariant find_default_value(int id);
bool is_equal_default_value(const CHANGEDOPT& opt, int type);
bool set_opt_value_for_OPTVAL(QVariant val, int type, OPTVAL* ov);
virtual void closeEvent(QCloseEvent* e);
int find_covered_scheme(OPTSCHEME& scheme); // return [1, schemes_.size()]
void save_scheme(void);
void cancel_setting(void);
static int find_opt_setting(const char* name, const std::vector<OPTVAL>& opts);
int apply_setting(const SANE_Option_Descriptor* desc, int opt_ind, OPTVAL* val);
int apply_settings(OPTSCHEME* scheme);
void record_changed_option(int opt, const QVariant& var);
void getAppVersion();
void apply_current_scheme(void);
private:
QVector<QPair<QPair<int, QVariant>, QString>> m_list_IdValueTitle;
@ -145,7 +124,6 @@ private:
QString m_colorModeValue;
SANE_Gamma m_gammaData;
QComboBox *comb_;
config *m_config;
};
#endif // HG_SETTING_DIALOG_H

View File

@ -1,772 +0,0 @@

#include "json.h"
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#define bzero(b, s) memset(b, 0, s)
#endif
namespace gb
{
static std::vector<std::string> split_with(const char* str, const char* splitor = "/")
{
std::vector<std::string> ret;
std::string src(str);
size_t pos = src.find(splitor);
while(pos != std::string::npos)
{
if(pos++)
ret.push_back(src.substr(0, pos - 1));
src.erase(0, pos + strlen(splitor));
pos = src.find(splitor);
}
if(src.length())
ret.push_back(src);
return ret;
}
json::json(char* json_txt) : obj_(0), cur_child_(0), is_array_(false)
{
attach_text(json_txt);
}
json::~json()
{
clear();
}
std::string json::to_string(cJSON* root, bool formatted)
{
char* txt = formatted ? cJSON_Print(root) : cJSON_PrintUnformatted(root);
std::string ret(txt ? txt : "");
if (txt)
free(txt);
return ret;
}
std::string json::get_value_as_string(cJSON* root, bool integer)
{
std::string ret("");
switch (root->type)
{
case cJSON_False:
ret = "false";
break;
case cJSON_True:
ret = "true";
break;
case cJSON_NULL:
ret = "null";
break;
case cJSON_Number:
{
char buf[40];
if (integer)
sprintf(buf, "%d", root->valueint);
else
sprintf(buf, "%f", root->valuedouble);
ret = buf;
}
break;
case cJSON_String:
if (root->valuestring)
ret = root->valuestring;
break;
default:
ret = json::to_string(root, false);
break;
}
return ret;
}
void json::free_node_data(cJSON* node)
{
if (node->type == cJSON_String && node->valuestring)
free(node->valuestring);
else if((node->type == cJSON_Object || node->type == cJSON_Array) && node->child)
cJSON_Delete(node->child);
node->type = cJSON_NULL;
node->valuestring = NULL;
node->child = NULL;
}
cJSON* json::create_element_with_name(const char* name)
{
cJSON* obj = cJSON_CreateObject();
bzero(obj, sizeof(*obj));
if(name)
{
obj->string = (char*)malloc(strlen(name) + 4);
bzero(obj->string, strlen(name) + 4);
strcpy(obj->string, name);
}
return obj;
}
cJSON* json::find_sibling(cJSON* first, const char* name, cJSON*** prev)
{
cJSON* now = first, **prv = NULL;
while(now)
{
if(now->string && strcmp(now->string, name) == 0)
{
break;
}
prv = &now->next;
now = now->next;
}
if(prev)
*prev = prv;
return now;
}
cJSON* json::find_child(cJSON *parent, std::vector<std::string>& path, bool create, cJSON*** addr)
{
if(!parent->child)
{
if(!create)
return NULL;
parent->child = json::create_element_with_name(path[0].c_str());
if(path.size() == 1)
{
if(addr)
*addr = &parent->child;
return parent->child;
}
}
cJSON** prev = NULL,
*now = find_sibling(parent->child, path[0].c_str(), &prev);
if(!now)
{
if(!create)
return now;
now = json::create_element_with_name(path[0].c_str());
if(prev)
*prev = now;
else
{
obj_->child = now;
prev = &obj_->child;
}
}
path.erase(path.begin());
if(path.empty())
{
if(addr)
*addr = prev ? prev : &parent->child;
return now;
}
return find_child(now, path, create, addr);
}
cJSON* json::find(const char* path, bool create, cJSON*** addr)
{
std::vector<std::string> tree(split_with(path));
if(tree.empty())
return NULL;
if(!obj_)
{
if(!create)
return NULL;
obj_ = cJSON_CreateObject();
obj_->child = json::create_element_with_name(tree[0].c_str());
}
return find_child(obj_, tree, create, addr);
}
bool json::attach_text(char* json_txt)
{
clear();
obj_ = cJSON_Parse(json_txt);
if(obj_)
is_array_ = obj_->type == cJSON_Array;
return obj_ != 0;
}
bool json::attach_cjson(cJSON* cjson)
{
clear();
if (cjson)
{
std::string txt(json::to_string(cjson, false));
if (txt.length())
obj_ = cJSON_Parse(txt.c_str());
}
if(obj_)
is_array_ = obj_->type == cJSON_Array;
return obj_ != 0;
}
bool json::create_empty(bool array)
{
clear();
obj_ = array ? cJSON_CreateArray() : cJSON_CreateObject();
is_array_ = array;
return true;
}
void json::clear(void)
{
if (obj_)
{
cJSON_Delete(obj_);
obj_ = 0;
}
}
std::string json::to_string(bool formatted)
{
if (obj_)
return json::to_string(obj_, formatted);
else
return "";
}
bool json::get_value(const char* key, bool& val)
{
cJSON* obj = find(key);
if (!obj)
return false;
if (obj->type == cJSON_True)
val = true;
else if (obj->type == cJSON_False)
val = false;
else
return false;
return true;
}
bool json::get_value(const char* key, int& val)
{
cJSON* obj = find(key);
if (!obj)
return false;
if (obj->type != cJSON_Number)
return false;
val = obj->valueint;
return true;
}
bool json::get_value(const char* key, double& val)
{
cJSON *obj = find(key);
if (!obj)
return false;
if (obj->type != cJSON_Number)
return false;
val = obj->valuedouble;
return true;
}
bool json::get_value(const char* key, std::string& val)
{
cJSON *obj = find(key);
if (!obj)
return false;
if (obj->type != cJSON_String)
return false;
val = obj->valuestring ? obj->valuestring : "";
return true;
}
bool json::get_value(const char* key, json*& val)
{
cJSON *obj = find(key);
if (!obj)
return false;
val = new json();
if (!val->attach_cjson(obj))
{
delete val;
return false;
}
return true;
}
bool json::get_value_as_string(const char* key, std::string& val, bool integer)
{
cJSON* obj = find(key);
if (!obj)
return false;
val = json::get_value_as_string(obj, integer);
return true;
}
bool json::get_as_array(const char* key, std::vector<std::string>& val)
{
cJSON *obj = find(key);
val.clear();
if (obj && obj->type == cJSON_Array)
{
cJSON *child = obj->child;
while (child)
{
if (child->type == cJSON_Number)
{
char buf[40];
sprintf(buf, "%d", child->valueint);
val.push_back(buf);
}
else if (child->type == cJSON_String)
val.push_back(child->valuestring ? child->valuestring : "");
else
{
char *text = cJSON_Print(child);
val.push_back(text);
free(text);
}
child = child->next;
}
return true;
}
return false;
}
bool json::first_child(std::string& val, std::string* name)
{
cur_child_ = obj_->child;
val = "";
if (cur_child_)
{
val = json::get_value_as_string(cur_child_);
if (name && cur_child_->string)
*name = cur_child_->string;
return true;
}
else
{
return false;
}
}
bool json::next_child(std::string& val, std::string* name)
{
if (cur_child_)
cur_child_ = cur_child_->next;
val = "";
if (cur_child_)
{
val = json::get_value_as_string(cur_child_);
if (name && cur_child_->string)
*name = cur_child_->string;
return true;
}
else
{
return false;
}
}
bool json::set_value(const char* key, bool val)
{
if(!key)
{
if(is_array_)
{
if(!obj_)
obj_ = cJSON_CreateArray();
cJSON_AddItemToArray(obj_, val ? cJSON_CreateTrue() : cJSON_CreateFalse());
}
return is_array_;
}
cJSON* ele = this->find(key, true);
if (!ele)
return false;
json::free_node_data(ele);
if (val)
ele->type = cJSON_True;
else
ele->type = cJSON_False;
return true;
}
bool json::set_value(const char* key, int val)
{
if(!key)
{
if(is_array_)
{
if(!obj_)
obj_ = cJSON_CreateArray();
cJSON_AddItemToArray(obj_, cJSON_CreateNumber(val));
}
return is_array_;
}
cJSON* ele = this->find(key, true);
if (!ele)
return false;
json::free_node_data(ele);
ele->type = cJSON_Number;
ele->valuedouble = ele->valueint = val;
return true;
}
bool json::set_value(const char* key, double val)
{
if(!key)
{
if(is_array_)
{
if(!obj_)
obj_ = cJSON_CreateArray();
cJSON_AddItemToArray(obj_, cJSON_CreateNumber(val));
}
return is_array_;
}
cJSON* ele = this->find(key, true);
if (!ele)
return false;
json::free_node_data(ele);
ele->type = cJSON_Number;
ele->valuedouble = val;
return true;
}
bool json::set_value(const char* key, std::string val)
{
if(!key)
{
if(is_array_)
{
if(!obj_)
obj_ = cJSON_CreateArray();
cJSON_AddItemToArray(obj_, cJSON_CreateString(val.c_str()));
}
return is_array_;
}
cJSON* ele = this->find(key, true);
if (!ele)
return false;
json::free_node_data(ele);
ele->type = cJSON_String;
ele->valuestring = (char*)malloc(val.length() + 4);
bzero(ele->valuestring, val.length() + 4);
strcpy(ele->valuestring, val.c_str());
return true;
}
bool json::set_value(const char* key, const char* val)
{
return set_value(key, std::string(val));
}
bool json::set_value(const char* key, json* obj)
{
if(!key)
{
if(is_array_)
{
if(!obj_)
obj_ = cJSON_CreateArray();
if(obj && obj->obj_)
{
cJSON_AddItemToArray(obj_, obj->obj_);
obj->obj_ = NULL;
}
}
return is_array_;
}
cJSON** addr = NULL;
cJSON* ele = this->find(key, true, &addr);
if (!ele)
return false;
// json::free_node_data(ele);
cJSON_Delete(ele);
*addr = obj->obj_;
ele = obj->obj_;
if(ele->string)
free(ele->string);
ele->string = (char*)malloc(strlen(key) + 4);
bzero(ele->string, strlen(key) + 4);
strcpy(ele->string, key);
obj->obj_ = NULL;
return true;
}
bool json::remove(const char* key)
{
if(!obj_)
return false;
cJSON **addr = NULL,
*ele = find(key, false, &addr);
if(ele)
{
if(addr)
*addr = NULL;
cJSON_Delete(ele);
return true;
}
else
return false;
}
}
namespace gb
{
static char base64_default_table[] = { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" };
base64::base64() : padding_char_('=')
{
base64_ind_[0] = base64_char_[0] = 0;
initialize_base64_table(base64_default_table);
}
base64::~base64()
{}
bool base64::is_valid_base64_table(const char* table)
{
bool valid = false;
if (table && strlen(table) >= 64)
{
char repeat[4] = { 0 };
valid = true;
for (int i = 0; i < 63; ++i)
{
repeat[0] = table[i];
if (strstr(table + i + 1, repeat))
{
valid = false;
break;
}
}
}
return valid;
}
bool base64::initialize_base64_table(const char* table)
{
if (!table || strlen(table) < 64)
{
if (memcmp(base64_default_table, base64_char_, 64) == 0)
{
return !table;
}
memcpy(base64_char_, base64_default_table, 64);
}
else
{
if (memcmp(base64_char_, table, 64) == 0)
{
return true;
}
else if (!is_valid_base64_table(table))
return false;
memcpy(base64_char_, table, 64);
}
base64_char_[64] = base64_char_[65] = 0;
// initialize base64_index
memset(base64_ind_, 0, sizeof(base64_ind_));
for (int i = 0; i < 64; ++i)
{
base64_ind_[base64_char_[i]] = i;
}
// padding char
padding_char_ = '=';
if (base64_ind_[padding_char_])
{
for (padding_char_ = 0x21; padding_char_ < 0x7e && base64_ind_[padding_char_] && padding_char_ != base64_char_[0]; ++padding_char_);
}
return padding_char_ < 0x7e;
}
bool base64::set_base64_table(const char* table)
{
return initialize_base64_table(table ? table : base64_default_table);
}
std::string base64::encode(const char* data, size_t bytes, unsigned int line_bytes, bool need_padding)
{
char* str = (char*)malloc(bytes * 2 + 3);
unsigned char c1 = 0, c2 = 0, c3 = 0;
unsigned long line_len = 0;
unsigned long words = bytes / 3;
int rest = bytes % 3,
pos = 0;
std::string ret("");
for (unsigned long i = 0; i < words; ++i)
{
// fetch 3 letters
c1 = *data++;
c2 = *data++;
c3 = *data++;
// encoding into 4-bytes
str[pos++] = base64_char_[c1 >> 2];
str[pos++] = base64_char_[((c1 << 4) | (c2 >> 4)) & 0x3f];
str[pos++] = base64_char_[((c2 << 2) | (c3 >> 6)) & 0x3f];
str[pos++] = base64_char_[c3 & 0x3f];
line_len += 4;
// new line ...
if ((unsigned int)line_len > line_bytes - 4)
{
str[pos++] = '\r';
str[pos++] = '\n';
line_len = 0;
}
}
// rest ...
if (rest == 1)
{
c1 = *data++;
str[pos++] = base64_char_[(c1 & 0xfc) >> 2];
str[pos++] = base64_char_[((c1 & 0x03) << 4)];
if (need_padding)
{
str[pos++] = padding_char_;
str[pos++] = padding_char_;
}
}
else if (rest == 2)
{
c1 = *data++;
c2 = *data++;
str[pos++] = base64_char_[(c1 & 0xfc) >> 2];
str[pos++] = base64_char_[((c1 & 0x03) << 4) | ((c2 & 0xf0) >> 4)];
str[pos++] = base64_char_[((c2 & 0x0f) << 2)];
if (need_padding)
{
str[pos++] = padding_char_;
}
}
if (pos > 0)
{
str[pos++] = 0;
ret = std::string(str, pos - 1);
}
free(str);
return ret;
}
std::string base64::decode(const char* data, size_t bytes)
{
char* str = (char*)malloc(bytes + 1);
int pos = 0,
shifts = 18,
value = 0;
std::string ret("");
for (int i = 0; i < (int)bytes; ++i)
{
if (*data != '\r' && *data != '\n')
{
if (*data == padding_char_)
{
break;
}
value += base64_ind_[*data] << shifts;
if (shifts == 0)
{
shifts = 18;
str[pos++] = (value >> 16) & 0x0ff;
str[pos++] = (value >> 8) & 0x0ff;
str[pos++] = (value >> 0) & 0x0ff;
value = 0;
}
else
{
shifts -= 6;
}
}
data++;
}
if (shifts == 12 || shifts == 6)
{
str[pos++] = (value >> 16) & 0x0ff;
}
else if (shifts == 0)
{
str[pos++] = (value >> 16) & 0x0ff;
str[pos++] = (value >> 8) & 0x0ff;
}
if (pos > 0)
{
str[pos++] = 0;
ret = std::string(str, pos - 1);
}
free(str);
return ret;
}
}

View File

@ -1,79 +0,0 @@
#pragma once
#ifdef WIN32
#include <Windows.h>
#endif
#include "cJSON.h"
#include <vector>
#include <string>
namespace gb
{
class json
{
cJSON *obj_;
cJSON* cur_child_;
bool is_array_;
cJSON* find_sibling(cJSON* first, const char* name, cJSON*** addr);
cJSON* find_child(cJSON *parent, std::vector<std::string>& path, bool create, cJSON*** addr = NULL);
cJSON* find(const char* path, bool create = false, cJSON*** addr = NULL);
public:
json(char* json_txt = 0);
~json();
static std::string to_string(cJSON* root, bool formatted);
static std::string get_value_as_string(cJSON* root, bool integer = false);
static void free_node_data(cJSON* node);
static cJSON* create_element_with_name(const char* name);
public:
bool attach_text(char* json_txt);
bool attach_cjson(cJSON* cjson);
bool create_empty(bool array = false);
void clear(void);
std::string to_string(bool formatted);
// can be path: child/value ...
bool get_value(const char* key, bool& val);
bool get_value(const char* key, int& val);
bool get_value(const char* key, double& val);
bool get_value(const char* key, std::string& val);
bool get_value(const char* key, json*& val); // caller shoud call "delete" to free the returned object !!!
bool get_value_as_string(const char* key, std::string& val, bool integer);
bool get_as_array(const char* key, std::vector<std::string>& val);
bool first_child(std::string& val, std::string* name = NULL);
bool next_child(std::string& val, std::string* name = NULL);
bool set_value(const char* key, bool val);
bool set_value(const char* key, int val);
bool set_value(const char* key, double val);
bool set_value(const char* key, std::string val);
bool set_value(const char* key, const char* val);
bool set_value(const char* key, json* obj);
bool remove(const char* key);
};
class base64
{
char base64_ind_[128];
char base64_char_[80];
char padding_char_;
bool is_valid_base64_table(const char* table);
bool initialize_base64_table(const char* table);
public:
base64();
~base64();
public:
bool set_base64_table(const char* table = NULL);
std::string encode(const char* data, size_t bytes, unsigned int line_bytes = -1, bool need_padding = true);
std::string decode(const char* data, size_t bytes);
};
}

View File

@ -112,7 +112,13 @@ MainWindow::MainWindow(QWidget *parent)
m_versionDll->PostUserOpenInfo(HGVERSION_APPNAME_SCANNER);
}
m_config.load();
HGChar cfgpath[512] = {0};
QString old;
HGBase_GetConfigPath(cfgpath, _countof(cfgpath) - 1);
dev_que_.set_root_dir(cfgpath);
old = QString::fromStdString(cfgpath) + PATH_SYMBOL + "scanner.schm";
if(QFile::exists(old))
dev_que::update_old_cfg(old.toStdString().c_str());
ui->toolBar->addAction(ui->act_scannerSettings);
ui->toolBar->addAction(ui->act_acquire);
@ -292,7 +298,7 @@ MainWindow::MainWindow(QWidget *parent)
m_password = passwordDecrypt(password);
m_dlgFullScreen = nullptr;
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(!dev_que_.opened_scanner_name().empty() && 0 != m_scanType, m_isScanning);
updateActionStatus();
ui->act_autoSave->setChecked(auto_save_changes_);
ui->act_autoSave->setText(tr("auto save"));
@ -320,7 +326,6 @@ MainWindow::~MainWindow()
m_dlgFullScreen = nullptr;
}
cur_dev_.close();
sane_exit();
m_versionDll->PostDeviceCloseInfo(m_currDeviceName.toStdString().c_str(), m_devSerialNum.toStdString().c_str(), "", m_devVersionNum.toStdString().c_str());
@ -537,7 +542,7 @@ void MainWindow::on_currItemChanged(int index)
bool save = false;
if(auto_save_changes_)
{
// 切换图片时,自动保存编辑过的图像。若想取消,请取消勾选菜单项:图像->自动保存
// 切æ<EFBFBD>¢å¾ç‰‡æ—¶ï¼Œè‡ªåŠ¨ä¿<EFBFBD>å­˜ç¼è¾è¿‡çš„å¾åƒ<EFBFBD>ã€è¥æƒ³å<EFBFBD>消,请å<EFBFBD>消å¾é€‰è<EFBFBD>œå<EFBFBD>•é¡¹ï¼šå¾åƒ?>自动ä¿<C3A4>å­˜
QString info(tr("Automatically save the edited the edited iamge when switching pictures. To cancel, uncheck the menu item: image-> automatically save"));
m_wndStatusBar->setDeviceStatusInfo(info, false);
save = true;
@ -779,15 +784,14 @@ void MainWindow::on_clearCache()
void MainWindow::on_sane_dev_arrive(QString devName, bool opened)
{
bool reconnected = false;
if(std::find(dev_schemes_.begin(), dev_schemes_.end(), devName.toStdString()) == dev_schemes_.end())
std::vector<std::string> now;
std::string stdn(devName.toStdString());
dev_que_.get_scanners(now);
if(std::find(now.begin(), now.end(), stdn) == now.end())
{
// initializing the device configuration ...
DEVCFG cfg;
cfg.m_deviceName = devName.toStdString();
cfg.m_originDeviceName = devName.toStdString();
m_config.load_scanner_configs(devName, &cfg);
dev_schemes_.push_back(cfg);
ui->menu_device->deviceMenuUpdate(&dev_schemes_, m_currDeviceName.toStdString());
dev_que_.add_scanner(stdn.c_str());
// statu info ...
QString info(tr("found device ") +": " + devName);
@ -807,31 +811,20 @@ void MainWindow::on_sane_dev_arrive(QString devName, bool opened)
m_dialogLog->addLog(info, !opened);
HGBase_WriteInfo(!opened ? HGBASE_INFOTYPE_ERROR : HGBASE_INFOTYPE_DESC, "%s", getStdString(info).c_str());
reconnected = true;
dev_que_.set_online(true, stdn.c_str());
}
// enable the device menu item ...
ui->menu_device->connectedDevice(devName);
// open it if no device has been opened ...
if (!cur_dev_.is_online())
if (dev_que_.opened_scanner_name().empty())
{
if (cur_dev_.handle() && devName.toStdString() == cur_dev_.name())
{
cur_dev_.set_online(true);
}
else
{
std::vector<DEVCFG>::iterator it = std::find(dev_schemes_.begin(), dev_schemes_.end(), devName.toStdString());
OPTSCHEME *schm = nullptr;
if(it!= dev_schemes_.end())
schm = it->get_current();
open_scanner(devName, schm);
}
dev_que_.open_scanner(stdn.c_str());
}
ui->menu_device->deviceMenuUpdate(&dev_que_);
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(!dev_que_.opened_scanner_name().empty() && 0 != m_scanType, m_isScanning);
updateActionStatus();
}
@ -842,18 +835,15 @@ void MainWindow::on_sane_dev_remove(QString devName)
m_wndStatusBar->setDeviceStatusInfo(info, true);
m_dialogLog->addLog(info, true);
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "%s", getStdString(info).c_str());
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "%s", getStdString(info).c_str());
// enable the device menu item ...
ui->menu_device->disconnectedDevice(devName);
// set openning device offline ...
if(devName.toStdString() == cur_dev_.name())
{
cur_dev_.set_online(false);
}
dev_que_.set_online(false, devName.toStdString().c_str());
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
updateActionStatus();
}
@ -1121,7 +1111,7 @@ void MainWindow::on_scan_finish(QString finishInfo, int err)
m_currScanCount = 0;
m_isScanning = false;
m_thumb->setAcceptDrops(true);
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
updateActionStatus();
m_wndStatusBar->setDeviceStatusInfo(finishInfo, (err != SANE_STATUS_GOOD));
m_dialogLog->addLog(finishInfo, (err != SANE_STATUS_GOOD), LOG_EVENT_SCAN_STOPPED);
@ -1142,7 +1132,7 @@ void MainWindow::on_continueScan()
return;
}
if (!cur_dev_.is_online() || m_isScanning || 0 == m_scanType)
if (!dev_que_.is_online() || m_isScanning || 0 == m_scanType)
{
return;
}
@ -1158,9 +1148,9 @@ void MainWindow::on_continueScan()
m_dpi = getDpi();
if (m_singleScan)
ret = sane_io_control(cur_dev_.handle(), IO_CTRL_CODE_TEST_SINGLE, nullptr, nullptr);
ret = sane_io_control(dev_que_.handle(), IO_CTRL_CODE_TEST_SINGLE, nullptr, nullptr);
else
ret = sane_start(cur_dev_.handle());
ret = sane_start(dev_que_.handle());
if (ret != SANE_STATUS_GOOD)
{
m_wndStatusBar->setDeviceStatusInfo(tr("start failed"), true);
@ -1191,7 +1181,7 @@ void MainWindow::on_continueScan()
{
m_isScanning = true;
m_thumb->setAcceptDrops(false);
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
updateActionStatus();
}
@ -1200,7 +1190,7 @@ void MainWindow::on_continueScan()
void MainWindow::on_stopScan()
{
m_dialogLog->updateStatus(cur_dev_.is_online(), m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online(), m_isScanning);
if (!m_isScanning)
{
@ -1215,9 +1205,9 @@ void MainWindow::on_stopScan()
}
else
{
if (cur_dev_.is_online())
if (dev_que_.is_online())
{
sane_cancel(cur_dev_.handle());
sane_cancel(dev_que_.handle());
}
}
}
@ -1322,17 +1312,17 @@ HGUInt MainWindow::getDpi()
{
HGUInt dpi = 200;
SANE_Int num_dev_options = 0;
sane_control_option(cur_dev_.handle(), 0, SANE_ACTION_GET_VALUE, &num_dev_options, nullptr);
sane_control_option(dev_que_.handle(), 0, SANE_ACTION_GET_VALUE, &num_dev_options, nullptr);
for (int i = 1; i < num_dev_options; ++i)
{
const SANE_Option_Descriptor* desp = sane_get_option_descriptor(cur_dev_.handle(), i);
const SANE_Option_Descriptor* desp = sane_get_option_descriptor(dev_que_.handle(), i);
if (nullptr == desp)
continue;
if (SANE_TYPE_INT == desp->type)
{
SANE_Int value = 0;
sane_control_option(cur_dev_.handle(), i, SANE_ACTION_GET_VALUE, &value, nullptr);
sane_control_option(dev_que_.handle(), i, SANE_ACTION_GET_VALUE, &value, nullptr);
if (0 == strcmp(desp->name, SANE_STD_OPT_NAME_RESOLUTION))
{
dpi = (HGUInt)value;
@ -1452,41 +1442,41 @@ void MainWindow::updateActionStatus()
selectIndexs.push_back(i);
}
ui->act_open->setEnabled(!cur_dev_.is_online() || !m_isScanning);
ui->act_insert->setEnabled(!cur_dev_.is_online() || !m_isScanning);
ui->act_open->setEnabled(!dev_que_.is_online() || !m_isScanning);
ui->act_insert->setEnabled(!dev_que_.is_online() || !m_isScanning);
ui->act_save->setEnabled(nullptr != img && -1 != m_currIndex && m_multiPageCount == 1
&& (!cur_dev_.is_online() || !m_isScanning));
&& (!dev_que_.is_online() || !m_isScanning));
ui->act_saveAs->setEnabled(nullptr != img);
ui->act_Export->setEnabled(0 != count && (!cur_dev_.is_online() || !m_isScanning));
ui->act_closeFile->setEnabled(!selectIndexs.empty() && (!cur_dev_.is_online() || !m_isScanning));
ui->act_closeAll->setEnabled(0 != count && (!cur_dev_.is_online() || !m_isScanning));
ui->act_imageInfo->setEnabled(-1 != m_currIndex && (!cur_dev_.is_online() || !m_isScanning));
ui->menu_multiPages->setEnabled(m_multiPageCount > 1 && (!cur_dev_.is_online() || !m_isScanning));
ui->act_Export->setEnabled(0 != count && (!dev_que_.is_online() || !m_isScanning));
ui->act_closeFile->setEnabled(!selectIndexs.empty() && (!dev_que_.is_online() || !m_isScanning));
ui->act_closeAll->setEnabled(0 != count && (!dev_que_.is_online() || !m_isScanning));
ui->act_imageInfo->setEnabled(-1 != m_currIndex && (!dev_que_.is_online() || !m_isScanning));
ui->menu_multiPages->setEnabled(m_multiPageCount > 1 && (!dev_que_.is_online() || !m_isScanning));
ui->act_previous->setEnabled(count > 0 && (-1 == m_currIndex || m_currIndex > 0)
&& (!cur_dev_.is_online() || !m_isScanning));
&& (!dev_que_.is_online() || !m_isScanning));
ui->act_next->setEnabled(count > 0 && (-1 == m_currIndex || m_currIndex < count - 1)
&& (!cur_dev_.is_online() || !m_isScanning));
ui->act_first->setEnabled(count > 0 && 0 != m_currIndex && (!cur_dev_.is_online() || !m_isScanning));
ui->act_last->setEnabled(count > 0 && count - 1 != m_currIndex && (!cur_dev_.is_online() || !m_isScanning));
ui->act_openPageNum->setEnabled(count > 0 && (!cur_dev_.is_online() || !m_isScanning));
&& (!dev_que_.is_online() || !m_isScanning));
ui->act_first->setEnabled(count > 0 && 0 != m_currIndex && (!dev_que_.is_online() || !m_isScanning));
ui->act_last->setEnabled(count > 0 && count - 1 != m_currIndex && (!dev_que_.is_online() || !m_isScanning));
ui->act_openPageNum->setEnabled(count > 0 && (!dev_que_.is_online() || !m_isScanning));
ui->act_previousPage->setEnabled(-1 != m_currIndex && m_multiPageCount > 0 && m_multiIndex > 0
&& (!cur_dev_.is_online() || !m_isScanning));
&& (!dev_que_.is_online() || !m_isScanning));
ui->act_nextPage->setEnabled(-1 != m_currIndex && m_multiPageCount > 0 && -1 != m_multiIndex && m_multiIndex < m_multiPageCount - 1
&& (!cur_dev_.is_online() || !m_isScanning));
&& (!dev_que_.is_online() || !m_isScanning));
ui->act_firstPage->setEnabled(-1 != m_currIndex && m_multiPageCount > 0 && 0 != m_multiIndex
&& (!cur_dev_.is_online() || !m_isScanning));
&& (!dev_que_.is_online() || !m_isScanning));
ui->act_lastPage->setEnabled(-1 != m_currIndex && m_multiPageCount > 0 && m_multiIndex != m_multiPageCount - 1
&& (!cur_dev_.is_online() || !m_isScanning));
&& (!dev_que_.is_online() || !m_isScanning));
m_multiPageLineEdit->setText(QString("%1/%2").arg(m_multiIndex + 1).arg(m_multiPageCount));
ui->toolBar->actions().at(16)->setVisible(-1 != m_currIndex && m_multiPageCount > 1 && -1 != m_multiIndex
&& (!cur_dev_.is_online() || !m_isScanning));
ui->act_sortPages->setEnabled(0 != count && (!cur_dev_.is_online() || !m_isScanning));
&& (!dev_que_.is_online() || !m_isScanning));
ui->act_sortPages->setEnabled(0 != count && (!dev_que_.is_online() || !m_isScanning));
ui->act_imageEdit->setEnabled(nullptr != img);
ui->act_zoomIn->setEnabled(nullptr != img);
ui->act_zoomOut->setEnabled(nullptr != img);
ui->act_fullscreen->setEnabled(count > 0 && -1 != m_currIndex && -1 != m_multiIndex
&& (!cur_dev_.is_online() || !m_isScanning));
&& (!dev_que_.is_online() || !m_isScanning));
ui->act_fitWindowSize->setEnabled(nullptr != img);
ui->act_fitWindowWidth->setEnabled(nullptr != img);
ui->act_realSize->setEnabled(nullptr != img);
@ -1495,8 +1485,8 @@ void MainWindow::updateActionStatus()
ui->act_180->setEnabled(nullptr != img);
ui->menu_Auto_Image_Size->setEnabled(nullptr != img);
ui->act_adjust->setEnabled(nullptr != img);
ui->act_multiRotate->setEnabled(0 != count && (!cur_dev_.is_online() || !m_isScanning));
ui->menu_Rotate->setEnabled((0 != count || nullptr != img) && (!cur_dev_.is_online() || !m_isScanning));
ui->act_multiRotate->setEnabled(0 != count && (!dev_que_.is_online() || !m_isScanning));
ui->menu_Rotate->setEnabled((0 != count || nullptr != img) && (!dev_que_.is_online() || !m_isScanning));
ui->act_autoCrop->setEnabled(nullptr != img);
ui->act_signIn->setEnabled(!m_admin_loggedIn);
@ -1507,17 +1497,17 @@ void MainWindow::updateActionStatus()
ui->act_consume->setEnabled(m_admin_loggedIn);
ui->act_clearRoller->setEnabled(m_admin_loggedIn);
ui->act_acquireInto->setEnabled(cur_dev_.is_online() && !m_isScanning);
ui->act_acquireSingle->setEnabled(cur_dev_.is_online() && !m_isScanning);
ui->act_acquire->setEnabled(cur_dev_.is_online() && !m_isScanning);
ui->act_scannerSettings->setEnabled(cur_dev_.is_online() && !m_isScanning);
ui->act_insertFromScanner->setEnabled(cur_dev_.is_online() && !m_isScanning);
ui->menu_scan->setEnabled(cur_dev_.is_online() && !m_isScanning);
ui->menu_device->setEnabled(!cur_dev_.is_online() || !m_isScanning);
ui->act_device_log->setEnabled(m_admin_loggedIn && !m_isScanning && cur_dev_.is_online());
ui->act_acquireInto->setEnabled(dev_que_.is_online() && !m_isScanning);
ui->act_acquireSingle->setEnabled(dev_que_.is_online() && !m_isScanning);
ui->act_acquire->setEnabled(dev_que_.is_online() && !m_isScanning);
ui->act_scannerSettings->setEnabled(dev_que_.is_online() && !m_isScanning);
ui->act_insertFromScanner->setEnabled(dev_que_.is_online() && !m_isScanning);
ui->menu_scan->setEnabled(dev_que_.is_online() && !m_isScanning);
ui->menu_device->setEnabled(!dev_que_.is_online() || !m_isScanning);
ui->act_device_log->setEnabled(m_admin_loggedIn && !m_isScanning && dev_que_.is_online());
ui->act_driver_log->setEnabled(m_admin_loggedIn);
m_moveToAction->setEnabled(!selectIndexs.empty() && (!cur_dev_.is_online() || !m_isScanning));
m_moveToAction->setEnabled(!selectIndexs.empty() && (!dev_que_.is_online() || !m_isScanning));
}
void MainWindow::startSaveMessageBox(QWidget* parent)
@ -1914,7 +1904,7 @@ void MainWindow::on_act_save_triggered()
if (!judgeDiskSpace(savePath))
{
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
return;
}
@ -2089,7 +2079,7 @@ void MainWindow::on_act_saveAs_triggered()
if(!judgeDiskSpace(savePath))
{
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
return;
}
@ -2193,7 +2183,7 @@ void MainWindow::on_act_Export_triggered()
if(!judgeDiskSpace(fileName))
{
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
return;
}
}
@ -2743,7 +2733,7 @@ void MainWindow::on_act_clearRoller_triggered()
return;
unsigned int count = 0;
int ret = sane_io_control(cur_dev_.handle(), IO_CTRL_CODE_CLEAR_ROLLER_COUNT, nullptr, &count);
int ret = sane_io_control(dev_que_.handle(), IO_CTRL_CODE_CLEAR_ROLLER_COUNT, nullptr, &count);
if(ret == SANE_STATUS_GOOD)
{
@ -2814,15 +2804,14 @@ void MainWindow::my_url_handler(const QUrl& url)
if(msg.clickedButton() == msg.button(QMessageBox::Yes))
{
unsigned int count = 0;
int ret = sane_io_control(cur_dev_.handle(), IO_CTRL_CODE_CLEAR_ROLLER_COUNT, nullptr, &count);
int ret = sane_io_control(dev_que_.handle(), IO_CTRL_CODE_CLEAR_ROLLER_COUNT, nullptr, &count);
QString info;
if(ret == SANE_STATUS_GOOD)
{
info = tr("Roller scanned count has been set to 0.");
// +请重新进入关于界面以获取最新值
info += tr("Please re-enter the Abount screen to obtain the latest value");
// +请é‡<C3A9>æ°è¿å…¥å…³äºŽç•Œé<C592>¢ä»¥èŽ·å<C2B7>最æ°å€? info += tr("Please re-enter the Abount screen to obtain the latest value");
}
else
info = tr("Roller scanned count reset failed.");
@ -2853,13 +2842,13 @@ void MainWindow::on_act_about_triggered()
.arg(appName).arg("v2.0.9.061").arg(copyRight).arg(developer).arg(website).arg(contact).arg(afterSelesContact).arg(address).arg(navigation));
QDesktopServices::setUrlHandler(MY_URL_SCHEME, this, "my_url_handler");
if (sane_io_control(cur_dev_.handle(), IO_CTRL_CODE_ABOUT_INFO, about, &len) == SANE_STATUS_NO_MEM)
if (sane_io_control(dev_que_.handle(), IO_CTRL_CODE_ABOUT_INFO, about, &len) == SANE_STATUS_NO_MEM)
{
about = (SANE_About*)malloc(len + 128);
if (about)
{
memset(about, 0, len + 128);
if (sane_io_control(cur_dev_.handle(), IO_CTRL_CODE_ABOUT_INFO, about, &len) == SANE_STATUS_GOOD)
if (sane_io_control(dev_que_.handle(), IO_CTRL_CODE_ABOUT_INFO, about, &len) == SANE_STATUS_GOOD)
{
title = tr("about %1").arg(QString::fromStdString(about->title));
content = tr("<p>Version: %1</p>").arg(QString::fromStdString(about->version));
@ -2890,45 +2879,14 @@ void MainWindow::on_act_about_triggered()
void MainWindow::on_act_scannerSettings_triggered()
{
if (!cur_dev_.is_online() || m_isScanning)
if (!dev_que_.is_online() || m_isScanning)
{
return;
}
DEVCFG cfg;
int m = 0;
for(; m < (int)dev_schemes_.size(); ++m)
{
std::string t = dev_schemes_[m].m_originDeviceName;
cfg.m_deviceName = cur_dev_.name();
if(strcmp(t.c_str(), cur_dev_.name().c_str()) == 0)
{
cfg = dev_schemes_[m];
dev_schemes_.erase(dev_schemes_.begin() + m);
break;
}
}
hg_settingdialog dlg(cur_dev_.handle(), this, &cfg);
dlg.set_config_file(&m_config);
hg_settingdialog dlg(dev_que_.handle(), this, &dev_que_);
dlg.exec();
int changes = dlg.get_changed_items();
dev_schemes_.insert(dev_schemes_.begin(), cfg);
if(changes)
{
m_config.save_scanner_configs(&cfg);
ui->menu_device->deviceMenuUpdate(&dev_schemes_, m_currDeviceName.toStdString());
QString dev(QString::fromStdString(cfg.m_deviceName)), scheme("");
if(cfg.get_current())
scheme = QString::fromStdString(cfg.get_current()->m_schemeTitle);
else if(cfg.schemes.size())
scheme = QString::fromStdString(cfg.schemes[0].m_schemeTitle);
ui->menu_device->setOptionChecked(dev, scheme, true);
// setWindowTitle(dev + "(" + scheme + ")");
}
ui->menu_device->deviceMenuUpdate(&dev_que_);
}
void MainWindow::on_act_acquire_triggered()
@ -2938,7 +2896,7 @@ void MainWindow::on_act_acquire_triggered()
return;
}
if (!cur_dev_.is_online() || m_isScanning)
if (!dev_que_.is_online() || m_isScanning)
{
return;
}
@ -2958,17 +2916,17 @@ void MainWindow::on_act_acquire_triggered()
if (!startSpaceCheck(this))
{
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
return;
}
startSaveMessageBox(this);
m_dpi = getDpi();
SANE_Status ret = sane_start(cur_dev_.handle());
SANE_Status ret = sane_start(dev_que_.handle());
if (ret != SANE_STATUS_GOOD)
{
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
m_wndStatusBar->setDeviceStatusInfo(tr("start failed"), true);
m_dialogLog->addLog(tr("start failed") + "(" + QString(sane_err_desc(ret)) + ")", true);
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "%s", getStdString(tr("start failed")).c_str());
@ -2997,7 +2955,7 @@ void MainWindow::on_act_acquire_triggered()
{
m_isScanning = true;
m_thumb->setAcceptDrops(false);
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
updateActionStatus();
}
@ -3011,7 +2969,7 @@ void MainWindow::on_act_acquireSingle_triggered()
return;
}
if (!cur_dev_.is_online() || m_isScanning)
if (!dev_que_.is_online() || m_isScanning)
{
return;
}
@ -3031,17 +2989,17 @@ void MainWindow::on_act_acquireSingle_triggered()
if (!startSpaceCheck(this))
{
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
return;
}
startSaveMessageBox(this);
m_dpi = getDpi();
SANE_Status ret = sane_io_control(cur_dev_.handle(), IO_CTRL_CODE_TEST_SINGLE, nullptr, nullptr);
SANE_Status ret = sane_io_control(dev_que_.handle(), IO_CTRL_CODE_TEST_SINGLE, nullptr, nullptr);
if (ret != SANE_STATUS_GOOD)
{
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
m_wndStatusBar->setDeviceStatusInfo(tr("start failed"), true);
m_dialogLog->addLog(tr("start failed") + "(" + QString(sane_err_desc(ret)) + ")", true);
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "%s", getStdString(tr("start failed")).c_str());
@ -3070,7 +3028,7 @@ void MainWindow::on_act_acquireSingle_triggered()
{
m_isScanning = true;
m_thumb->setAcceptDrops(false);
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
updateActionStatus();
}
@ -3079,7 +3037,7 @@ void MainWindow::on_act_acquireSingle_triggered()
void MainWindow::on_act_acquireInto_triggered()
{
if (!cur_dev_.is_online() || m_isScanning)
if (!dev_que_.is_online() || m_isScanning)
{
return;
}
@ -3120,17 +3078,17 @@ void MainWindow::on_act_acquireInto_triggered()
if (!startSpaceCheck(this))
{
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
return;
}
startSaveMessageBox(this);
m_dpi = getDpi();
SANE_Status ret = sane_start(cur_dev_.handle());
SANE_Status ret = sane_start(dev_que_.handle());
if (ret != SANE_STATUS_GOOD)
{
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
m_wndStatusBar->setDeviceStatusInfo(tr("start failed"), true);
m_dialogLog->addLog(tr("start failed") + "(" + QString(sane_err_desc(ret)) + ")", true);
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "%s", getStdString(tr("start failed")).c_str());
@ -3159,7 +3117,7 @@ void MainWindow::on_act_acquireInto_triggered()
{
m_isScanning = true;
m_thumb->setAcceptDrops(false);
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
updateActionStatus();
}
@ -3174,7 +3132,7 @@ void MainWindow::on_act_insertFromScanner_triggered()
return;
}
if (!cur_dev_.is_online() || m_isScanning)
if (!dev_que_.is_online() || m_isScanning)
{
return;
}
@ -3208,17 +3166,17 @@ void MainWindow::on_act_insertFromScanner_triggered()
if (!startSpaceCheck(this))
{
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
return;
}
startSaveMessageBox(this);
m_dpi = getDpi();
SANE_Status ret = sane_start(cur_dev_.handle());
SANE_Status ret = sane_start(dev_que_.handle());
if (ret != SANE_STATUS_GOOD)
{
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
m_wndStatusBar->setDeviceStatusInfo(tr("start failed"), true);
m_dialogLog->addLog(tr("start failed") + "(" + QString(sane_err_desc(ret)) + ")", true);
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "%s", getStdString(tr("start failed")).c_str());
@ -3247,7 +3205,7 @@ void MainWindow::on_act_insertFromScanner_triggered()
{
m_isScanning = true;
m_thumb->setAcceptDrops(false);
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
updateActionStatus();
}
@ -3331,9 +3289,9 @@ void MainWindow::on_act_imageEdit_triggered()
}
}
bool MainWindow::open_scanner(const QString& name, OPTSCHEME* schm)
bool MainWindow::open_scanner(const QString& name, const QString& scheme)
{
bool ret = cur_dev_.open(name.toStdString());
bool ret = dev_que_.open_scanner(name.toStdString().c_str(), scheme.toStdString().c_str()) == SANE_STATUS_GOOD;
QString info(tr("open scanner ") + " " + name + " ");
QString title(tr("app name"));
@ -3341,21 +3299,21 @@ bool MainWindow::open_scanner(const QString& name, OPTSCHEME* schm)
{
std::string serialNum;
unsigned int serialNumLen = 0;
if(SANE_STATUS_NO_MEM == sane_io_control(cur_dev_.handle(), IO_CTRL_CODE_GET_SERIAL, nullptr, &serialNumLen)
if(SANE_STATUS_NO_MEM == sane_io_control(dev_que_.handle(), IO_CTRL_CODE_GET_SERIAL, nullptr, &serialNumLen)
&& serialNumLen)
{
serialNum.resize(serialNumLen);
sane_io_control(cur_dev_.handle(), IO_CTRL_CODE_GET_SERIAL, &serialNum[0], &serialNumLen);
sane_io_control(dev_que_.handle(), IO_CTRL_CODE_GET_SERIAL, &serialNum[0], &serialNumLen);
}
m_devSerialNum = QString::fromStdString(serialNum);
std::string versionNum;
unsigned int versionNumLen = 0;
if(SANE_STATUS_NO_MEM == sane_io_control(cur_dev_.handle(), IO_CTRL_CODE_GET_HARDWARE_VERSION, nullptr, &versionNumLen)
if(SANE_STATUS_NO_MEM == sane_io_control(dev_que_.handle(), IO_CTRL_CODE_GET_HARDWARE_VERSION, nullptr, &versionNumLen)
&& versionNumLen)
{
versionNum.resize(versionNumLen);
sane_io_control(cur_dev_.handle(), IO_CTRL_CODE_GET_HARDWARE_VERSION, &versionNum[0], &versionNumLen);
sane_io_control(dev_que_.handle(), IO_CTRL_CODE_GET_HARDWARE_VERSION, &versionNum[0], &versionNumLen);
}
m_devVersionNum = QString::fromStdString(versionNum);
@ -3368,26 +3326,6 @@ bool MainWindow::open_scanner(const QString& name, OPTSCHEME* schm)
m_dialogLog->addLog(info, false);
HGBase_WriteInfo(HGBASE_INFOTYPE_DESC, "%s", getStdString(info).c_str());
bool apply = false;
if(schm)
{
apply = cur_dev_.apply_setting(schm);
info = tr("apply setting ") + QString::fromStdString(schm->m_schemeTitle) + (apply ? tr(" success") : tr(" failed"));
ui->menu_device->setOptionChecked(name, QString::fromStdString(schm->m_schemeTitle), apply);
if(apply)
title += "(" + QString::fromStdString(schm->m_schemeTitle) + ")";
}
if(!apply)
{
DEVCFG first;
if(first.schemes.size())
{
ui->menu_device->setOptionChecked(name, QString::fromStdString(first.schemes[0].m_schemeTitle), true);
title += "(" + QString::fromStdString(first.schemes[0].m_schemeTitle) + ")";
}
}
m_wndStatusBar->setDeviceStatusInfo(tr("be ready"), false);
}
else
@ -3398,7 +3336,7 @@ bool MainWindow::open_scanner(const QString& name, OPTSCHEME* schm)
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "%s", getStdString(info).c_str());
}
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
updateActionStatus();
// setWindowTitle(title);
return ret;
@ -3591,75 +3529,30 @@ void MainWindow::on_scanOptions_changed(const QString &device, const QString &op
QString title(tr("app name"));
if(checked_now)
{
OPTSCHEME *schm = nullptr;
int ind = config::find_config(device, dev_schemes_);
if(ind == -1)
std::string curdev(dev_que_.opened_scanner_name());
int ret = 0;
if(curdev != device.toStdString())
{
QString info(tr("lost config") + ": " + device);
m_wndStatusBar->setDeviceStatusInfo(info, true);
m_dialogLog->addLog(info, true);
HGBase_WriteInfo(HGBASE_INFOTYPE_ERROR, "%s", getStdString(info).c_str());
if(cur_dev_.name() != device.toStdString())
open_scanner(device, nullptr);
return;
ret = dev_que_.open_scanner(device.toStdString().c_str(), option.toStdString().c_str());
}
DEVCFG& cfg = dev_schemes_[ind];
// std::vector<OPTSCHEME>::iterator it = std::find(cfg.schemes.begin(), cfg.schemes.end(), option.toStdString());
// if(it == cfg.schemes.end())
// cfg.cur_scheme = -1;
int m = 0;
for(; m < (int)cfg.schemes.size(); ++m)
{
std::string t = cfg.schemes[m].m_schemeTitle;
if(strcmp(t.c_str(), option.toStdString().c_str()) == 0)
{
schm = &(cfg.schemes[m]);
cfg.cur_scheme = m - 1;
break;
}
else
{
cfg.cur_scheme = -1;
}
}
m_config.save_scanner_configs(&cfg);
if(cur_dev_.name() != device.toStdString())
{
if(!open_scanner(device, schm))
ui->menu_device->setOptionChecked(device, option, false);
return;
else {
ret = dev_que_.apply_scheme(option.toStdString().c_str());
}
QString info(tr("apply setting") + " '" + option + "' ");
bool ok = cur_dev_.apply_setting(schm); // check result ?
if(ok)
if(ret == 0)
{
info += tr("success");
cfg.select(option.toStdString().c_str());
}
else
{
ui->menu_device->setOptionChecked(device, option, false);
{
DEVCFG init;
if(init.schemes.size())
{
std::string name(init.schemes[0].m_schemeTitle);
cfg.select(name.c_str());
ui->menu_device->setOptionChecked(device, QString::fromStdString(name), true);
}
}
info += tr("failed");
}
m_config.save_scanner_configs(&cfg);
m_wndStatusBar->setDeviceStatusInfo(info, !ok);
m_dialogLog->addLog(info, !ok);
HGBase_WriteInfo(!ok ? HGBASE_INFOTYPE_ERROR : HGBASE_INFOTYPE_DESC, "%s", getStdString(info).c_str());
m_wndStatusBar->setDeviceStatusInfo(info, ret != 0);
m_dialogLog->addLog(info, ret != 0);
HGBase_WriteInfo(ret != 0 ? HGBASE_INFOTYPE_ERROR : HGBASE_INFOTYPE_DESC, "%s", getStdString(info).c_str());
title = device + "(" + option + ")";
}
else
@ -3672,7 +3565,7 @@ void MainWindow::on_scanOptions_changed(const QString &device, const QString &op
msg.exec();
if(msg.clickedButton() == msg.button(QMessageBox::Yes))
{
cur_dev_.close();
dev_que_.close_scanner();
m_versionDll->PostDeviceCloseInfo(device.toStdString().c_str(), m_devSerialNum.toStdString().c_str(), "", m_devVersionNum.toStdString().c_str());
m_dialogLog->addLog(tr("close ") + device, false);
@ -3684,14 +3577,14 @@ void MainWindow::on_scanOptions_changed(const QString &device, const QString &op
}
}
m_dialogLog->updateStatus(cur_dev_.is_online() && 0 != m_scanType, m_isScanning);
m_dialogLog->updateStatus(dev_que_.is_online() && 0 != m_scanType, m_isScanning);
updateActionStatus();
// setWindowTitle(title);
}
void MainWindow::on_act_sortPages_triggered()
{
if (cur_dev_.is_online() && m_isScanning)
if (dev_que_.is_online() && m_isScanning)
{
return;
}
@ -3781,7 +3674,7 @@ void MainWindow::on_act_driver_log_triggered()
{
char log_file_path[260] = {0};
unsigned int type = SANE_LogFileType::LOG_FILE_DRIVER;
SANE_Status statu = sane_io_control(cur_dev_.handle(), IO_CTRL_CODE_GET_LOG_FILE, log_file_path, &type);
SANE_Status statu = sane_io_control(dev_que_.handle(), IO_CTRL_CODE_GET_LOG_FILE, log_file_path, &type);
if(statu == SANE_STATUS_GOOD)
{
if(log_file_path[0])
@ -3799,7 +3692,7 @@ void MainWindow::on_act_device_log_triggered()
{
char log_file_path[260] = {0};
unsigned int type = SANE_LogFileType::LOG_FILE_DEVICE;
SANE_Status statu = sane_io_control(cur_dev_.handle(), IO_CTRL_CODE_GET_LOG_FILE, log_file_path, &type);
SANE_Status statu = sane_io_control(dev_que_.handle(), IO_CTRL_CODE_GET_LOG_FILE, log_file_path, &type);
if(statu == SANE_STATUS_GOOD)
{
if(log_file_path[0])

View File

@ -7,14 +7,12 @@
#include "HGImgView.h"
#include "HGImgThumb.h"
#include "sane/sane_ex.h"
#include "config.h"
#include "dialog_aquireinto.h"
#include "imgfmt/HGImgFmt.h"
#include "VersionDll.h"
#include "device_menu.h"
#include "sane_device.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
@ -235,7 +233,7 @@ private:
bool startSpaceCheck(QWidget* parent);
QString passwordEncrypt(const QString& password);
QString passwordDecrypt(const QString& transcode);
bool open_scanner(const QString& name, OPTSCHEME* schm);
bool open_scanner(const QString& name, const QString& scheme);
bool judgeDiskSpace(QString currentPath);
void upgradeApp(QString pkgPath);
bool isLimitAccessFolder(QString filePath);
@ -251,9 +249,7 @@ private:
QAction *m_moveToAction;
QListWidget* m_listwidget;
config m_config;
sane_dev cur_dev_;
std::vector<DEVCFG> dev_schemes_;
dev_que dev_que_;
bool auto_save_changes_;
bool save_from_changed_;

View File

@ -8,108 +8,14 @@ sane_dev::~sane_dev()
close();
}
bool sane_dev::apply(OPTSCHEME* schm)
bool sane_dev::apply(gb::sane_config_schm* schm)
{
SANE_Int count = 0,
afterdo = 0;
bool ret = false;
if(sane_control_option(hdev_, 0, SANE_ACTION_GET_VALUE, &count, &afterdo) == SANE_STATUS_GOOD)
{
int applied = 0;
for(int i = 1; i < count; ++i)
{
const SANE_Option_Descriptor* desc = sane_get_option_descriptor(hdev_, i);
if(!desc)
continue;
if(desc->type == SANE_TYPE_GROUP ||
desc->type == SANE_TYPE_BUTTON)
continue;
act_result result = apply(desc, i, schm->opts);
if(result == ACT_RESULT_NO_NEED)
continue;
if(result == ACT_RESULT_SUCCESS)
applied++;
else
break;
}
ret = schm->opts.size() == applied;
}
if(ret)
cfg_name_ = schm->m_schemeTitle;
return ret;
}
sane_dev::act_result sane_dev::apply(const SANE_Option_Descriptor* desc, int opt, const std::vector<OPTVAL>& vals)
{
act_result result = ACT_RESULT_NO_NEED;
const OPTVAL *cfg = nullptr;
for(size_t i = 0; i < vals.size(); ++i)
{
if(vals[i].name == desc->name)
{
cfg = &vals[i];
break;
}
}
if(cfg)
{
SANE_Int afterdo = 0;
void *data = nullptr, *str = nullptr;
SANE_Int nv = 0;
SANE_Bool bv = false;
SANE_Fixed fv = 0;
result = ACT_RESULT_FAILED;
if(desc->type == SANE_TYPE_INT)
{
nv = atoi(cfg->val.c_str());
data = &nv;
}
else if(desc->type == SANE_TYPE_BOOL)
{
bv = cfg->val == "true";
data = &bv;
}
else if(desc->type == SANE_TYPE_FIXED)
{
fv = SANE_FIX(atof(cfg->val.c_str()));
data = &fv;
}
else if(desc->type == SANE_TYPE_STRING)
{
int len = (int)cfg->val.length() > desc->size * 4 ? cfg->val.length() : desc->size * 4;
str = new char[len + 4];
if(str)
{
memset(str, 0, len + 4);
strcpy((char*)str, cfg->val.c_str());
data = str;
}
}
if(data)
result = sane_control_option(hdev_, opt, SANE_ACTION_SET_VALUE, data, &afterdo) == SANE_STATUS_GOOD ? ACT_RESULT_SUCCESS : result;
if(str)
delete[] str;
if(cfg->name == SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA && cfg->val == "true")
{
SANE_Gamma gamma = {0};
unsigned int l = 0;
if(config::load_custom_gamma(cfg->extra.c_str(), &gamma))
sane_io_control(hdev_, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &gamma, &l);
}
}
return result;
}
std::string sane_dev::name(void)
{
@ -138,40 +44,10 @@ bool sane_dev::open(const std::string& name)
SANE_Status statu = sane_open(name.c_str(), &hdev_);
if(statu == SANE_STATUS_GOOD)
{
DEVCFG first;
name_ = name;
offline_ = false;
if(first.schemes.size())
cfg_name_ = first.schemes[0].m_schemeTitle;
}
return statu == SANE_STATUS_GOOD;
}
bool sane_dev::apply_setting(OPTSCHEME* schm)
{
bool ret = false;
if(hdev_)
{
if(sane_io_control(hdev_, IO_CTRL_CODE_RESTORE_SETTINGS, nullptr, nullptr) == SANE_STATUS_GOOD)
{
DEVCFG first;
if(first.schemes.size())
cfg_name_ = first.schemes[0].m_schemeTitle;
if(schm)
{
ret = apply(schm);
}
else
{
ret = true;
}
}
}
return ret;
}
void sane_dev::set_online(bool online)
{
offline_ = !online;

View File

@ -2,7 +2,7 @@
#include <string>
#include "sane/sane_ex.h"
#include "config.h"
#include "cfg/gb_json.h"
@ -20,8 +20,7 @@ class sane_dev
ACT_RESULT_SUCCESS,
};
bool apply(OPTSCHEME* schm);
act_result apply(const SANE_Option_Descriptor* desc, int opt, const std::vector<OPTVAL>& vals);
bool apply(gb::sane_config_schm* schm);
public:
sane_dev();
@ -34,7 +33,6 @@ public:
SANE_Handle handle(void);
bool open(const std::string& name);
bool apply_setting(OPTSCHEME* schm = nullptr);
void set_online(bool online);
void close(void);
};

View File

@ -188,9 +188,8 @@ SOURCES += \
../../../app/scanner/widget_statusbar.cpp \
../../../app/scanner/dialog_admin.cpp \
../../../app/scanner/dialog_log.cpp \
../../../app/scanner/config.cpp \
../../../app/scanner/json.cpp \
../../../app/scanner/cJSON.c \
../../../app/scanner/cfg/gb_json.cpp \
../../../app/scanner/cfg/cJSON.c \
../../../app/scanner/HGImgThumb.cpp \
../../../app/scanner/HGImgView.cpp \
../../../app/scanner/HGUIGlobal.cpp \
@ -237,8 +236,8 @@ HEADERS += \
../../../app/scanner/dialog_admin.h \
../../../app/scanner/dialog_log.h \
../../../app/scanner/config.h \
../../../app/scanner/json.h \
../../../app/scanner/cJSON.h \
../../../app/scanner/cfg/gb_json.h \
../../../app/scanner/cfg/cJSON.h \
../../../app/scanner/HGImgThumb.h \
../../../app/scanner/HGImgView.h \
../../../app/scanner/HGUIGlobal.h \