保存用户自定义gamma数据,调整设置界面布局,日志窗口list默认为自动滚动

This commit is contained in:
gb 2022-05-07 16:12:34 +08:00
parent 537750b6dc
commit 60c954898d
8 changed files with 215 additions and 58 deletions

View File

@ -159,6 +159,34 @@ void config::to_lower(std::string& str)
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)
{

View File

@ -4,7 +4,8 @@
#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
@ -141,6 +142,7 @@ public:
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 = "");

View File

@ -35,7 +35,7 @@ dialog_log::dialog_log(QWidget *parent)
ui->verticalLayout->addItem(bottom);
cBox_autoScroll->setChecked(getCfgValue("log", "autoScroll", false));
cBox_autoScroll->setChecked(getCfgValue("log", "autoScroll", true));
connect(cBox_autoScroll, SIGNAL(stateChanged(int)), this, SLOT(on_cbox_autoScroll_stateChanged(int)));
connect(pbtn_stop, SIGNAL(clicked(bool)), this, SLOT(on_pbtn_stop_clicked()));

View File

@ -14,6 +14,7 @@ hg_settingdialog::hg_settingdialog(void *handle, QWidget *parent
, DEVCFG* cfg)
: QDialog(parent)
, schemes_(cfg), cur_ind_(cfg->cur_scheme), changed_count_(0), save_(false)
, btn_cut_area_(nullptr), btn_gamma_(nullptr), cfg_file_(nullptr)
{
m_dpiId = -1;
m_dpiValue = 200;
@ -33,6 +34,8 @@ hg_settingdialog::hg_settingdialog(void *handle, QWidget *parent
m_colorModeId = -1;
m_colorModeValue.clear();
memset(&m_gammaData, 0, sizeof(m_gammaData));
for(int i = 0; i < sizeof(m_gammaData.table) / sizeof(m_gammaData.table[0]); ++i)
m_gammaData.table[i] = i & 0x0ff;
m_handle = handle;
initUi();
@ -318,13 +321,48 @@ void hg_settingdialog::createUI()
if(schemes_ && cur_ind_ != -1)
ind = find_opt_setting(opt->title, schemes_->schemes[scheme].opts);
init.opt = i + 1;
h = nullptr;
switch (opt->type)
{
case SANE_TYPE_BOOL:
{
QCheckBox *checkBoxCreation = new QCheckBox(scrollArea);
reinterpret_cast<QFormLayout*>(widget->layout())->addRow(opt->title + QString(" : "), checkBoxCreation);
if (strcmp(opt->title, OPTION_TITLE_ZDYSMQY) == 0)
{
QLabel *title = new QLabel(scrollArea);
h = new QHBoxLayout();
title->setText(QString::fromStdString(opt->title) + QString(" : "));
h->addWidget(title);
h->addWidget(checkBoxCreation);
btn_cut_area_ = new QPushButton(this);
btn_cut_area_->setText(StdStringToUtf8("区域裁剪").c_str());
btn_cut_area_->setFixedWidth(120);
h->addWidget(btn_cut_area_);
reinterpret_cast<QFormLayout*>(widget->layout())->addRow(h);
connect(btn_cut_area_, SIGNAL(clicked(bool)), this, SLOT(slot_cutButtonClicked()));
}
else if (strcmp(opt->title, OPTION_TITLE_QYSDQX) == 0)
{
QLabel *title = new QLabel(scrollArea);
h = new QHBoxLayout();
title->setText(QString::fromStdString(opt->title) + QString(" : "));
h->addWidget(title);
h->addWidget(checkBoxCreation);
btn_gamma_ = new QPushButton(this);
btn_gamma_->setText(StdStringToUtf8("自定义色调曲线").c_str());
btn_gamma_->setFixedWidth(120);
h->addWidget(btn_gamma_);
reinterpret_cast<QFormLayout*>(widget->layout())->addRow(h);
connect(btn_gamma_, SIGNAL(clicked(bool)), this, SLOT(slot_gammaButtonClicked()));
}
else
reinterpret_cast<QFormLayout*>(widget->layout())->addRow(opt->title + QString(" : "), checkBoxCreation);
checkBoxCreation->setToolTip(opt->desc);
int id = i + 1;
checkBoxCreation->setProperty("controls_id", id);
if(ind != -1)
@ -332,6 +370,10 @@ void hg_settingdialog::createUI()
else
init.val = m_list_defaultOptions.at(i).second;
checkBoxCreation->setChecked(init.val.toBool());
if (strcmp(opt->title, OPTION_TITLE_ZDYSMQY) == 0)
btn_cut_area_->setEnabled(init.val.toBool());
else if (strcmp(opt->title, OPTION_TITLE_QYSDQX) == 0)
btn_gamma_->setEnabled(init.val.toBool());
connect(checkBoxCreation, SIGNAL(stateChanged(int)), this, SLOT(slot_checkedClicked()));
m_list_widgets.append(checkBoxCreation);
@ -649,35 +691,13 @@ void hg_settingdialog::createUI()
m_cutBottomValue = SANE_UNFIX(m_list_defaultOptions.at(i).second.toInt());
}
// if (Utf8ToStdString(opt->title) == "分辨率")
if (strcmp(opt->title, OPTION_TITLE_FBL) == 0)
{
QPushButton* pushButton = new QPushButton(this);
pushButton->setText(StdStringToUtf8("区域裁剪").c_str());
pushButton->setFixedWidth(120);
widget->layout()->addWidget(pushButton);
connect(pushButton, SIGNAL(clicked(bool)), this, SLOT(slot_cutButtonClicked()));
}
// else if (Utf8ToStdString(opt->title) == "颜色模式")
else if (strcmp(opt->title, OPTION_TITLE_YSMS) == 0)
if (strcmp(opt->title, OPTION_TITLE_YSMS) == 0)
{
m_colorModeId = i + 1;
m_colorModeValue = m_list_defaultOptions.at(i).second.toString();
}
// else if (Utf8ToStdString(opt->title) == "伽玛" || Utf8ToStdString(opt->title) == "伽玛值")
else if (strcmp(opt->title, OPTION_TITLE_GMZ) == 0)
{
unsigned int len = sizeof(SANE_Gamma);
sane_io_control(m_handle, IO_CTRL_CODE_GET_CUSTOM_GAMMA, &m_gammaData, &len);
QPushButton* pushButton = new QPushButton(this);
pushButton->setText(StdStringToUtf8("自定义色调曲线").c_str());
pushButton->setFixedWidth(120);
widget->layout()->addWidget(pushButton);
connect(pushButton, SIGNAL(clicked(bool)), this, SLOT(slot_gammaButtonClicked()));
}
if(init.opt != -1)
init_vals_.push_back(init);
@ -856,7 +876,8 @@ void hg_settingdialog::updateUIStatus()
if (widget == nullptr) continue;
QWidget* parentWidget = widget->parentWidget();
while (typeid(*(parentWidget->layout())) != typeid(QFormLayout))
while (parentWidget->layout() &&
typeid(*(parentWidget->layout())) != typeid(QFormLayout))
{
widget = parentWidget;
parentWidget = widget->parentWidget();
@ -864,19 +885,19 @@ void hg_settingdialog::updateUIStatus()
QFormLayout* layout = reinterpret_cast<QFormLayout*>(parentWidget->layout());
const SANE_Option_Descriptor* opt = reinterpret_cast<const SANE_Option_Descriptor*>(m_list_defaultOptions.at(id - 1).first);
bool hide = (opt->cap & SANE_CAP_INACTIVE) == SANE_CAP_INACTIVE;
QWidget* w_label = layout ? layout->labelForField(widget) : nullptr;
if( strcmp(opt->title, OPTION_TITLE_SMQYZCmm) == 0 ||
strcmp(opt->title, OPTION_TITLE_SMQYSCmm) == 0 ||
strcmp(opt->title, OPTION_TITLE_SMQYYCmm) == 0 ||
strcmp(opt->title, OPTION_TITLE_SMQYXCmm) == 0 )
hide = true;
refresh_control_value(id);
if((opt->cap & SANE_CAP_INACTIVE) == SANE_CAP_INACTIVE)
{
QWidget* w_label = layout->labelForField(widget);
if(w_label != nullptr)
w_label->hide();
widget->setVisible(false);
}else{
QWidget* w_label = layout->labelForField(widget);
if(w_label != nullptr)
w_label->show();
widget->setVisible(true);
}
if(w_label)
hide ? w_label->hide() : w_label->show();
widget->setVisible(!hide);
}
// Temporarily block the multi-stream output function
@ -887,7 +908,8 @@ void hg_settingdialog::updateUIStatus()
QWidget* w = m_list_widgets.at(i);
int id = w->property("controls_id").toInt();
const SANE_Option_Descriptor* opt = reinterpret_cast<const SANE_Option_Descriptor*>(m_list_defaultOptions.at(id - 1).first);
if(strcmp(opt->title, "24位彩色图像-多流输出") == 0)
// if(strcmp(opt->title, "24位彩色图像-多流输出") == 0)
if(strcmp(opt->title, OPTION_TITLE_24WCSTX_DLSCCH) == 0)
{
QFormLayout* layout = reinterpret_cast<QFormLayout*>(w->parentWidget()->layout());
QWidget* w_label = layout->labelForField(w);
@ -921,18 +943,11 @@ void hg_settingdialog::slot_checkedClicked()
else if(method & SANE_INFO_INEXACT)
checkBox->setCheckState(checkBoxcurrentState ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
std::vector<CHANGEDOPT>::iterator it =
std::find(changed_opts_.begin(), changed_opts_.end(), (int)id);
if(it == changed_opts_.end())
{
CHANGEDOPT co;
co.opt = id;
co.val = QVariant((bool)checkBoxcurrentState);
changed_opts_.push_back(co);
}
else {
it->val = QVariant((bool)checkBoxcurrentState);
}
if(strcmp(opt->title, OPTION_TITLE_ZDYSMQY) == 0)
btn_cut_area_->setEnabled(checkBoxcurrentState);
else if (strcmp(opt->title, OPTION_TITLE_QYSDQX) == 0)
btn_gamma_->setEnabled(checkBoxcurrentState);
record_changed_option((int)id, checkBoxcurrentState);
}
void hg_settingdialog::slot_string_list_comboBoxClicked()
@ -1514,6 +1529,10 @@ int hg_settingdialog::get_changed_items(void)
{
return changed_count_;
}
void hg_settingdialog::set_config_file(config* cfg)
{
cfg_file_ = cfg;
}
void hg_settingdialog::iniWrite(QString title, int id, QVariant value)
{
@ -1660,6 +1679,10 @@ void hg_settingdialog::on_select_scheme(int scheme_ind, bool apply_to_dev)
{
OPTSCHEME *schm = NULL;
memset(&m_gammaData, 0, sizeof(m_gammaData));
for(int i = 0; i < sizeof(m_gammaData.table) / sizeof(m_gammaData.table[0]); ++i)
m_gammaData.table[i] = i & 0x0ff;
changed_opts_.clear();
if(scheme_ind >= 0 && scheme_ind + 1 < (int)schemes_->schemes.size())
{
@ -1685,6 +1708,13 @@ void hg_settingdialog::on_select_scheme(int scheme_ind, bool apply_to_dev)
if(ok)
changed_opts_.push_back(co);
}
else if(schm->opts[i].name == OPTION_TITLE_ZDYGM)
{
co.opt = (int)OPTION_ID_ZDYGM;
co.val = QVariant(QString::fromStdString(schm->opts[i].val));
changed_opts_.push_back(co);
config::load_custom_gamma(schm->opts[i].val.c_str(), &m_gammaData);
}
}
}
@ -1730,6 +1760,8 @@ void hg_settingdialog::save_scheme(void)
int names = 0;
OPTVAL ov;
OPTSCHEME os;
bool save_gamma = false;
QString gamma_file("");
const SANE_Option_Descriptor *opt = nullptr;
if(cur_ind_ >= 0 && cur_ind_ + 1 < (int)schemes_->schemes.size())
@ -1739,7 +1771,13 @@ void hg_settingdialog::save_scheme(void)
{
opt = (const SANE_Option_Descriptor*)find_option_description(changed_opts_[i].opt);
if(!opt)
{
if(changed_opts_[i].opt == (int)OPTION_ID_ZDYGM)
{
gamma_file = changed_opts_[i].val.toString();
}
continue;
}
if(is_equal_default_value(changed_opts_[i], opt->type))
continue;
@ -1774,9 +1812,15 @@ void hg_settingdialog::save_scheme(void)
names++;
}
}
// custom gamma ...
if(strcmp(opt->title, OPTION_TITLE_QYSDQX) == 0 && ov.val == "true")
{
save_gamma = true;
}
}
if(os == src)
if(os == src && !save_gamma)
{
if(changed_count_ == 0)
changed_count_ = schemes_->cur_scheme != cur_ind_;
@ -1816,11 +1860,44 @@ void hg_settingdialog::save_scheme(void)
schemes_->schemes.erase(schemes_->schemes.begin() + cur_ind_ + 1);
}
else
{
gamma_file = "";
cur_ind_ = schemes_->schemes.size() - 1;
}
}
else
cur_ind_ = find_covered_scheme(os); // schemes_->schemes.size() - 1;
if(save_gamma)
{
if(gamma_file.length() == 0)
{
time_t now = time(nullptr);
tm *ptm = localtime(&now);
char name[40] = {0};
sprintf(name, "/%04d%02d%02d%02d%02d%02d.gma", ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
if(cfg_file_)
{
std::string str(cfg_file_->get_file().toStdString());
size_t pos = str.rfind('/');
if(pos == std::string::npos)
pos = str.rfind('\\');
if(pos != std::string::npos)
str.erase(pos);
gamma_file = QString::fromStdString(str);
}
else
gamma_file = config::self_path();
gamma_file += QString::fromStdString(name);
}
config::save_2_file(gamma_file, &m_gammaData, sizeof(m_gammaData));
ov.val = gamma_file.toStdString();
ov.type = "file";
ov.name = OPTION_TITLE_ZDYGM;
os.opts.push_back(ov);
}
schemes_->schemes.insert(schemes_->schemes.begin() + cur_ind_ + 1, os);
schemes_->cur_scheme = cur_ind_;
changed_count_++;
@ -2083,6 +2160,17 @@ void hg_settingdialog::slot_pushButton_scheme_management(void)
break;
}
}
OPTSCHEME* s = &schemes_->schemes[id + 1];
for(size_t i = 0; i < s->opts.size(); ++i)
{
if(s->opts[i].name == OPTION_TITLE_ZDYGM)
{
SANE_Gamma gmma;
if(config::load_custom_gamma(s->opts[i].val.c_str(), &gmma))
remove(s->opts[i].val.c_str());
}
}
schemes_->schemes.erase(schemes_->schemes.begin() + id + 1);
if(top_menu_->actions().size() == 0)
{
@ -2105,6 +2193,19 @@ void hg_settingdialog::slot_pushButton_scheme_management(void)
if (msg.clickedButton() != msg.button(QMessageBox::Yes))
return;
for(size_t i = 1; i < schemes_->schemes.size(); ++i)
{
OPTSCHEME* s = &schemes_->schemes[i];
for(size_t i = 0; i < s->opts.size(); ++i)
{
if(s->opts[i].name == OPTION_TITLE_ZDYGM)
{
SANE_Gamma gmma;
if(config::load_custom_gamma(s->opts[i].val.c_str(), &gmma))
remove(s->opts[i].val.c_str());
}
}
}
schemes_->schemes.erase(schemes_->schemes.begin() + 1, schemes_->schemes.end());
QAction* acts = top_menu_->addAction(tr("No custom configuration was found"));
acts->setEnabled(false);

View File

@ -29,6 +29,7 @@ class hg_settingdialog : public QDialog
std::vector<CHANGEDOPT> changed_opts_; // values which changed
int changed_count_;
bool save_;
config* cfg_file_;
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
@ -40,6 +41,8 @@ class hg_settingdialog : public QDialog
QPushButton *apply_;
QPushButton *del_this_;
QPushButton *del_all_;
QPushButton *btn_cut_area_;
QPushButton *btn_gamma_;
QTextEdit *sketch_;
void create_scheme_management_ui(QVBoxLayout* layout);
QAction* find_current_scheme_menu(int *scheme_id = NULL);
@ -65,6 +68,7 @@ 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;

View File

@ -2128,6 +2128,7 @@ void MainWindow::on_act_scannerSettings_triggered()
dev_schemes_.erase(it);
}
hg_settingdialog dlg(cur_dev_.handle(), this, &cfg);
dlg.set_config_file(&m_config);
dlg.exec();
int changes = dlg.get_changed_items();
dev_schemes_.insert(dev_schemes_.begin(), cfg);

View File

@ -20,22 +20,24 @@ bool sane_dev::apply(OPTSCHEME* schm)
for(int i = 1; i < count; ++i)
{
const SANE_Option_Descriptor* desc = sane_get_option_descriptor(hdev_, i);
int extra = 0;
if(!desc)
continue;
if(desc->type == SANE_TYPE_GROUP ||
desc->type == SANE_TYPE_BUTTON)
continue;
act_result result = apply(desc, i, schm->opts);
act_result result = apply(desc, i, schm->opts, &extra);
if(result == ACT_RESULT_NO_NEED)
continue;
if(result == ACT_RESULT_SUCCESS)
applied++;
applied += extra + 1;
else
break;
}
ret = schm->opts.size() == applied;
ret = schm->opts.size() <= applied;
}
if(ret)
@ -43,11 +45,13 @@ bool sane_dev::apply(OPTSCHEME* schm)
return ret;
}
sane_dev::act_result sane_dev::apply(const SANE_Option_Descriptor* desc, int opt, const std::vector<OPTVAL>& vals)
sane_dev::act_result sane_dev::apply(const SANE_Option_Descriptor* desc, int opt, const std::vector<OPTVAL>& vals, int *apply_extra)
{
act_result result = ACT_RESULT_NO_NEED;
const OPTVAL *cfg = nullptr;
if(apply_extra)
*apply_extra = 0;
for(size_t i = 0; i < vals.size(); ++i)
{
if(vals[i].name == desc->title)
@ -97,6 +101,23 @@ sane_dev::act_result sane_dev::apply(const SANE_Option_Descriptor* desc, int opt
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 == OPTION_TITLE_QYSDQX && cfg->val == "true")
{
for(size_t i = 0; i < vals.size(); ++i)
{
if(vals[i].name == OPTION_TITLE_ZDYGM)
{
SANE_Gamma gamma = {0};
unsigned int l = 0;
if(config::load_custom_gamma(vals[i].val.c_str(), &gamma))
sane_io_control(hdev_, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &gamma, &l);
if(apply_extra)
*apply_extra = 1;
break;
}
}
}
}
return result;

View File

@ -21,7 +21,7 @@ class sane_dev
};
bool apply(OPTSCHEME* schm);
act_result apply(const SANE_Option_Descriptor* desc, int opt, const std::vector<OPTVAL>& vals);
act_result apply(const SANE_Option_Descriptor* desc, int opt, const std::vector<OPTVAL>& vals, int *apply_extra = nullptr);
public:
sane_dev();