diff --git a/build2/qt/HGSaneUI/HGSaneUI.pro b/build2/qt/HGSaneUI/HGSaneUI.pro index e33672f5..b24ab1e7 100644 --- a/build2/qt/HGSaneUI/HGSaneUI.pro +++ b/build2/qt/HGSaneUI/HGSaneUI.pro @@ -131,6 +131,8 @@ unix { } INCLUDEPATH += $$PWD/../../../modules +INCLUDEPATH += $$PWD/../../../utility +INCLUDEPATH += $$PWD/../../../modules/saneui INCLUDEPATH += $$PWD/../../../../sdk/include DESTDIR = $$PWD/../../build/$${MY_OS}/$${OEM_NAME}/$${MY_ARCH}/$${MY_CONFIGURE} @@ -171,7 +173,7 @@ win32 { SRCDLL_FILE = $${DESTDIR}/$${TARGET}.dll SRCDLL_FILE = $$replace(SRCDLL_FILE, /, \\) message(SRCDLL_FILE: $$SRCDLL_FILE) - SRCHEADER_FILE = $${PWD}/../../../modules/saneui/*.h + SRCHEADER_FILE = $${PWD}/../../../modules/saneui/HGSaneUI.h SRCHEADER_FILE = $$replace(SRCHEADER_FILE, /, \\) message(SRCHEADER_FILE: $$SRCHEADER_FILE) SRCPDB_FILE = $${DESTDIR}/$${TARGET}.pdb @@ -202,15 +204,42 @@ unix { SOURCES += \ ../../../modules/saneui/HGSaneUI.cpp \ + ../../../modules/saneui/cfg/cJSON.c \ + ../../../modules/saneui/cfg/gb_json.cpp \ + ../../../modules/saneui/cutdialog.cpp \ + ../../../modules/saneui/cutpapertool.cpp \ + ../../../modules/saneui/device_menu.cpp \ ../../../modules/saneui/dialog_device_scan.cpp \ ../../../modules/saneui/dialog_device_select.cpp \ - ../../../modules/saneui/dllmain.cpp + ../../../modules/saneui/dialog_input.cpp \ + ../../../modules/saneui/dllmain.cpp \ + ../../../modules/saneui/gaosixy.cpp \ + ../../../modules/saneui/hg_settingdialog.cpp \ + ../../../modules/saneui/setpicclrtool.cpp \ + ../../../modules/saneui/widget.cpp \ + ../../../utility/HGString.cpp HEADERS += \ ../../../modules/saneui/HGSaneUI.h \ + ../../../modules/saneui/cfg/cJSON.h \ + ../../../modules/saneui/cfg/gb_json.h \ + ../../../modules/saneui/cutdialog.h \ + ../../../modules/saneui/cutpapertool.h \ + ../../../modules/saneui/device_menu.h \ ../../../modules/saneui/dialog_device_scan.hpp \ - ../../../modules/saneui/dialog_device_select.hpp + ../../../modules/saneui/dialog_device_select.hpp \ + ../../../modules/saneui/dialog_input.h \ + ../../../modules/saneui/gaosixy.h \ + ../../../modules/saneui/hg_settingdialog.h \ + ../../../modules/saneui/setpicclrtool.h \ + ../../../modules/saneui/widget.h \ + ../../../utility/HGString.h FORMS += \ + ../../../modules/saneui/cutdialog.ui \ + ../../../modules/saneui/cutpapertool.ui \ ../../../modules/saneui/dialog_device_scan.ui \ - ../../../modules/saneui/dialog_device_select.ui + ../../../modules/saneui/dialog_device_select.ui \ + ../../../modules/saneui/dialog_input.ui \ + ../../../modules/saneui/setpicclrtool.ui \ + ../../../modules/saneui/widget.ui diff --git a/modules/sane_user/HGSaneImpl.cpp b/modules/sane_user/HGSaneImpl.cpp index 36dfa3bb..942018f1 100644 --- a/modules/sane_user/HGSaneImpl.cpp +++ b/modules/sane_user/HGSaneImpl.cpp @@ -17,6 +17,7 @@ HGSaneManagerImpl::HGSaneManagerImpl() m_f_sane_get_parameters = NULL; m_f_sane_get_option_descriptor = NULL; m_f_sane_control_option = NULL; + m_f_sane_io_control = NULL; memset(&m_saneApi, 0, sizeof(SANEAPI)); } @@ -243,6 +244,10 @@ HGResult HGSaneManagerImpl::FindFunctions() if (HGBASE_ERR_OK != ret) break; + ret = HGBase_GetDllProcAddress(m_dll, "sane_hgsane_io_control", (HGPointer*)&m_f_sane_io_control); + if (HGBASE_ERR_OK != ret) + break; + } while (0); m_saneApi.sane_get_devices_api = m_f_sane_get_devices; @@ -256,6 +261,7 @@ HGResult HGSaneManagerImpl::FindFunctions() m_saneApi.sane_get_parameters_api = m_f_sane_get_parameters; m_saneApi.sane_get_option_descriptor_api = m_f_sane_get_option_descriptor; m_saneApi.sane_control_option_api = m_f_sane_control_option; + m_saneApi.sane_io_control_api = m_f_sane_io_control; return ret; } @@ -373,7 +379,7 @@ HGResult HGSaneDeviceImpl::ShowSettingDlg(HGWindow parent) return HGBASE_ERR_FAIL; } - if (-2 == show_setting_ui(&m_mgrImpl->m_saneApi, m_devHandle, parent)) + if (-2 == show_setting_ui(&m_mgrImpl->m_saneApi, m_devHandle, m_devName.c_str(), parent)) { return HGBASE_ERR_NOTSUPPORT; } diff --git a/modules/sane_user/HGSaneImpl.hpp b/modules/sane_user/HGSaneImpl.hpp index e7653daa..3a52bed3 100644 --- a/modules/sane_user/HGSaneImpl.hpp +++ b/modules/sane_user/HGSaneImpl.hpp @@ -25,6 +25,8 @@ typedef SANE_String_Const (*f_sane_strstatus)(SANE_Status status); typedef SANE_Status (*f_sane_get_parameters)(SANE_Handle handle, SANE_Parameters* params); typedef const SANE_Option_Descriptor* (*f_sane_get_option_descriptor)(SANE_Handle handle, SANE_Int option); typedef SANE_Status (*f_sane_control_option)(SANE_Handle handle, SANE_Int option, SANE_Action action, void* value, SANE_Int* info); +// 非标准接口 +typedef SANE_Status (*f_sane_io_control)(SANE_Handle h, unsigned long code, void* data, unsigned* len); class HGSaneManagerImpl { @@ -59,6 +61,7 @@ private: f_sane_get_parameters m_f_sane_get_parameters; f_sane_get_option_descriptor m_f_sane_get_option_descriptor; f_sane_control_option m_f_sane_control_option; + f_sane_io_control m_f_sane_io_control; SANEAPI m_saneApi; std::list m_listDeviceImpl; diff --git a/modules/saneui/HGSaneUI.cpp b/modules/saneui/HGSaneUI.cpp index c5b773bc..8d20b610 100644 --- a/modules/saneui/HGSaneUI.cpp +++ b/modules/saneui/HGSaneUI.cpp @@ -1,6 +1,7 @@ #include "HGSaneUI.h" #include "dialog_device_select.hpp" #include "dialog_device_scan.hpp" +#include "hg_settingdialog.h" #include "lang/app_language.h" #include #include @@ -53,7 +54,7 @@ int show_devlist_ui(SANEAPI* saneApi, HGWindow parent, SANE_Handle *handle, char return 0; } -int show_setting_ui(SANEAPI* saneApi, SANE_Handle handle, HGWindow parent) +int show_setting_ui(SANEAPI* saneApi, SANE_Handle handle, const char *scanner_name, HGWindow parent) { if (nullptr == saneApi || nullptr == handle) return -1; @@ -77,6 +78,8 @@ int show_setting_ui(SANEAPI* saneApi, SANE_Handle handle, HGWindow parent) translator.load(":translation/SaneUI_zh_CN.qm"); QCoreApplication::installTranslator(&translator); + hg_settingdialog dlg(saneApi, handle, scanner_name, qParent); + dlg.exec(); return 0; } diff --git a/modules/saneui/HGSaneUI.h b/modules/saneui/HGSaneUI.h index 72bf585b..47cb9e14 100644 --- a/modules/saneui/HGSaneUI.h +++ b/modules/saneui/HGSaneUI.h @@ -7,7 +7,7 @@ typedef void (*show_scan_ui_image_callback)(const SANE_Parameters *imageFormat, const SANE_Byte *imageData, void * callbackParam); HGEXPORT int show_devlist_ui(SANEAPI* saneApi, HGWindow parent, SANE_Handle *handle, char *devName, unsigned int maxLen); -HGEXPORT int show_setting_ui(SANEAPI* saneApi, SANE_Handle handle, HGWindow parent); +HGEXPORT int show_setting_ui(SANEAPI* saneApi, SANE_Handle handle, const char *scanner_name, HGWindow parent); HGEXPORT int show_scan_ui(SANEAPI* saneApi, SANE_Handle handle, HGWindow parent, show_scan_ui_image_callback callback, void *callbackParam); #endif diff --git a/modules/saneui/cfg/cJSON.c b/modules/saneui/cfg/cJSON.c new file mode 100644 index 00000000..f3dc5bcd --- /dev/null +++ b/modules/saneui/cfg/cJSON.c @@ -0,0 +1,756 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +/* cJSON */ +/* JSON parser in C. */ + +#include +#include +#include +#include +#include +#include +#include +#include "cJSON.h" + +static const char *ep; + +const char *cJSON_GetErrorPtr(void) {return ep;} + +static int cJSON_strcasecmp(const char *s1,const char *s2) +{ + if (!s1) return (s1==s2)?0:1;if (!s2) return 1; + for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0; + return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2); +} + +static void* ask_memory(size_t bytes) +{ +// printf("allocate %u bytes memory in cJSON\n", bytes); + + return malloc(bytes); +} +static void *(*cJSON_malloc)(size_t sz) = ask_memory; +static void (*cJSON_free)(void *ptr) = free; + +static char* cJSON_strdup(const char* str) +{ + size_t len; + char* copy; + + len = strlen(str) + 1; + if (!(copy = (char*)cJSON_malloc(len))) return 0; + memcpy(copy,str,len); + return copy; +} + +void cJSON_InitHooks(cJSON_Hooks* hooks) +{ + if (!hooks) { /* Reset hooks */ + cJSON_malloc = ask_memory; + cJSON_free = free; + return; + } + + cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:ask_memory; + cJSON_free = (hooks->free_fn)?hooks->free_fn:free; +} + +/* Internal constructor. */ +static cJSON *cJSON_New_Item(void) +{ + cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON)); + if (node) memset(node,0,sizeof(cJSON)); + return node; +} + +/* Delete a cJSON structure. */ +void cJSON_Delete(cJSON *c) +{ + cJSON *next; + while (c) + { + next=c->next; + if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child); + if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring); + if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string); + cJSON_free(c); + c=next; + } +} + +/* Parse the input text to generate a number, and populate the result into item. */ +static const char *parse_number(cJSON *item,const char *num) +{ + double n=0,sign=1,scale=0;int subscale=0,signsubscale=1; + + if (*num=='-') sign=-1,num++; /* Has sign? */ + if (*num=='0') num++; /* is zero */ + if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */ + if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */ + if (*num=='e' || *num=='E') /* Exponent? */ + { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */ + while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */ + } + + n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */ + + item->valuedouble=n; + item->valueint=(int)n; + item->type=cJSON_Number; + return num; +} + +static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; } + +typedef struct {char *buffer; int length; int offset; } printbuffer; + +static char* ensure(printbuffer *p,int needed) +{ + char *newbuffer;int newsize; + if (!p || !p->buffer) return 0; + needed+=p->offset; + if (needed<=p->length) return p->buffer+p->offset; + + newsize=pow2gt(needed); + newbuffer=(char*)cJSON_malloc(newsize); + if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;} + if (newbuffer) memcpy(newbuffer,p->buffer,p->length); + cJSON_free(p->buffer); + p->length=newsize; + p->buffer=newbuffer; + return newbuffer+p->offset; +} + +static int update(printbuffer *p) +{ + char *str; + if (!p || !p->buffer) return 0; + str=p->buffer+p->offset; + return p->offset+strlen(str); +} + +/* Render the number nicely from the given item into a string. */ +static char *print_number(cJSON *item,printbuffer *p) +{ + char *str=0; + double d=item->valuedouble; + if (d==0) + { + if (p) str=ensure(p,2); + else str=(char*)cJSON_malloc(2); /* special case for 0. */ + if (str) strcpy(str,"0"); + } + else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN) + { + if (p) str=ensure(p,21); + else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */ + if (str) sprintf(str,"%d",item->valueint); + } + else + { + if (p) str=ensure(p,64); + else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */ + if (str) + { + if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d); + else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d); + else sprintf(str,"%f",d); + } + } + return str; +} + +static unsigned parse_hex4(const char *str) +{ + unsigned h=0; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + h=h<<4;str++; + if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0; + return h; +} + +/* Parse the input text into an unescaped cstring, and populate item. */ +static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; +static const char *parse_string(cJSON *item,const char *str) +{ + const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2; + if (*str!='\"') {ep=str;return 0;} /* not a string! */ + + while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */ + + out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */ + if (!out) return 0; + + ptr=str+1;ptr2=out; + while (*ptr!='\"' && *ptr) + { + if (*ptr!='\\') *ptr2++=*ptr++; + else + { + ptr++; + switch (*ptr) + { + case 'b': *ptr2++='\b'; break; + case 'f': *ptr2++='\f'; break; + case 'n': *ptr2++='\n'; break; + case 'r': *ptr2++='\r'; break; + case 't': *ptr2++='\t'; break; + case 'u': /* transcode utf16 to utf8. */ + uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */ + + if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */ + + if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */ + { + if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */ + uc2=parse_hex4(ptr+3);ptr+=6; + if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */ + uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF)); + } + + len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len; + + switch (len) { + case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6; + case 1: *--ptr2 =(uc | firstByteMark[len]); + } + ptr2+=len; + break; + default: *ptr2++=*ptr; break; + } + ptr++; + } + } + *ptr2=0; + if (*ptr=='\"') ptr++; + item->valuestring=out; + item->type=cJSON_String; + return ptr; +} + +/* Render the cstring provided to an escaped version that can be printed. */ +static char *print_string_ptr(const char *str,printbuffer *p) +{ + const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token; + + for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0; + if (!flag) + { + len=ptr-str; + if (p) out=ensure(p,len+3); + else out=(char*)cJSON_malloc(len+3); + if (!out) return 0; + ptr2=out;*ptr2++='\"'; + strcpy(ptr2,str); + ptr2[len]='\"'; + ptr2[len+1]=0; + return out; + } + + if (!str) + { + if (p) out=ensure(p,3); + else out=(char*)cJSON_malloc(3); + if (!out) return 0; + strcpy(out,"\"\""); + return out; + } + ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;} + + if (p) out=ensure(p,len+3); + else out=(char*)cJSON_malloc(len+3); + if (!out) return 0; + + ptr2=out;ptr=str; + *ptr2++='\"'; + while (*ptr) + { + if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++; + else + { + *ptr2++='\\'; + switch (token=*ptr++) + { + case '\\': *ptr2++='\\'; break; + case '\"': *ptr2++='\"'; break; + case '\b': *ptr2++='b'; break; + case '\f': *ptr2++='f'; break; + case '\n': *ptr2++='n'; break; + case '\r': *ptr2++='r'; break; + case '\t': *ptr2++='t'; break; + default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */ + } + } + } + *ptr2++='\"';*ptr2++=0; + return out; +} +/* Invote print_string_ptr (which is useful) on an item. */ +static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);} + +/* Predeclare these prototypes. */ +static const char *parse_value(cJSON *item,const char *value); +static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p); +static const char *parse_array(cJSON *item,const char *value); +static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p); +static const char *parse_object(cJSON *item,const char *value); +static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p); + +/* Utility to jump whitespace and cr/lf */ +static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;} + +/* Parse an object - create a new root, and populate. */ +cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated) +{ + const char *end=0; + cJSON *c=cJSON_New_Item(); + ep=0; + if (!c) return 0; /* memory fail */ + + end=parse_value(c,skip(value)); + if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */ + + /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */ + if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}} + if (return_parse_end) *return_parse_end=end; + return c; +} +/* Default options for cJSON_Parse */ +cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);} + +/* Render a cJSON item/entity/structure to text. */ +char *cJSON_Print(cJSON *item) {return print_value(item,0,1,0);} +char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0,0);} + +char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt) +{ + printbuffer p; + p.buffer=(char*)cJSON_malloc(prebuffer); + p.length=prebuffer; + p.offset=0; + return print_value(item,0,fmt,&p); + return p.buffer; +} + + +/* Parser core - when encountering text, process appropriately. */ +static const char *parse_value(cJSON *item,const char *value) +{ + if (!value) return 0; /* Fail on null. */ + if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; } + if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; } + if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; } + if (*value=='\"') { return parse_string(item,value); } + if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); } + if (*value=='[') { return parse_array(item,value); } + if (*value=='{') { return parse_object(item,value); } + + ep=value;return 0; /* failure. */ +} + +/* Render a value to text. */ +static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p) +{ + char *out=0; + if (!item) return 0; + if (p) + { + switch ((item->type)&255) + { + case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;} + case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;} + case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;} + case cJSON_Number: out=print_number(item,p);break; + case cJSON_String: out=print_string(item,p);break; + case cJSON_Array: out=print_array(item,depth,fmt,p);break; + case cJSON_Object: out=print_object(item,depth,fmt,p);break; + } + } + else + { + switch ((item->type)&255) + { + case cJSON_NULL: out=cJSON_strdup("null"); break; + case cJSON_False: out=cJSON_strdup("false");break; + case cJSON_True: out=cJSON_strdup("true"); break; + case cJSON_Number: out=print_number(item,0);break; + case cJSON_String: out=print_string(item,0);break; + case cJSON_Array: out=print_array(item,depth,fmt,0);break; + case cJSON_Object: out=print_object(item,depth,fmt,0);break; + } + } + return out; +} + +/* Build an array from input text. */ +static const char *parse_array(cJSON *item,const char *value) +{ + cJSON *child; + if (*value!='[') {ep=value;return 0;} /* not an array! */ + + item->type=cJSON_Array; + value=skip(value+1); + if (*value==']') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; /* memory fail */ + value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_value(child,skip(value+1))); + if (!value) return 0; /* memory fail */ + } + + if (*value==']') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an array to text */ +static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p) +{ + char **entries; + char *out=0,*ptr,*ret;int len=5; + cJSON *child=item->child; + int numentries=0,i=0,fail=0; + size_t tmplen=0; + + /* How many entries in the array? */ + while (child) numentries++,child=child->next; + /* Explicitly handle numentries==0 */ + if (!numentries) + { + if (p) out=ensure(p,3); + else out=(char*)cJSON_malloc(3); + if (out) strcpy(out,"[]"); + return out; + } + + if (p) + { + /* Compose the output array. */ + i=p->offset; + ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++; + child=item->child; + while (child && !fail) + { + print_value(child,depth+1,fmt,p); + p->offset=update(p); + if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;} + child=child->next; + } + ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0; + out=(p->buffer)+i; + } + else + { + /* Allocate an array to hold the values for each */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + memset(entries,0,numentries*sizeof(char*)); + /* Retrieve all the results: */ + child=item->child; + while (child && !fail) + { + ret=print_value(child,depth+1,fmt,0); + entries[i++]=ret; + if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1; + child=child->next; + } + + /* If we didn't fail, try to ask_memory the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + /* If that fails, we fail. */ + if (!out) fail=1; + + /* Handle failure. */ + if (fail) + { + for (i=0;itype=cJSON_Object; + value=skip(value+1); + if (*value=='}') return value+1; /* empty array. */ + + item->child=child=cJSON_New_Item(); + if (!item->child) return 0; + value=skip(parse_string(child,skip(value))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + + while (*value==',') + { + cJSON *new_item; + if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */ + child->next=new_item;new_item->prev=child;child=new_item; + value=skip(parse_string(child,skip(value+1))); + if (!value) return 0; + child->string=child->valuestring;child->valuestring=0; + if (*value!=':') {ep=value;return 0;} /* fail! */ + value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */ + if (!value) return 0; + } + + if (*value=='}') return value+1; /* end of array */ + ep=value;return 0; /* malformed. */ +} + +/* Render an object to text. */ +static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p) +{ + char **entries=0,**names=0; + char *out=0,*ptr,*ret,*str;int len=7,i=0,j; + cJSON *child=item->child; + int numentries=0,fail=0; + size_t tmplen=0; + /* Count the number of entries. */ + while (child) numentries++,child=child->next; + /* Explicitly handle empty object case */ + if (!numentries) + { + if (p) out=ensure(p,fmt?depth+4:3); + else out=(char*)cJSON_malloc(fmt?depth+4:3); + if (!out) return 0; + ptr=out;*ptr++='{'; + if (fmt) {*ptr++='\n';for (i=0;ioffset; + len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0; + *ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len; + child=item->child;depth++; + while (child) + { + if (fmt) + { + ptr=ensure(p,depth); if (!ptr) return 0; + for (j=0;joffset+=depth; + } + print_string_ptr(child->string,p); + p->offset=update(p); + + len=fmt?2:1; + ptr=ensure(p,len); if (!ptr) return 0; + *ptr++=':';if (fmt) *ptr++='\t'; + p->offset+=len; + + print_value(child,depth,fmt,p); + p->offset=update(p); + + len=(fmt?1:0)+(child->next?1:0); + ptr=ensure(p,len+1); if (!ptr) return 0; + if (child->next) *ptr++=','; + if (fmt) *ptr++='\n';*ptr=0; + p->offset+=len; + child=child->next; + } + ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0; + if (fmt) for (i=0;ibuffer)+i; + } + else + { + /* Allocate space for the names and the objects */ + entries=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!entries) return 0; + names=(char**)cJSON_malloc(numentries*sizeof(char*)); + if (!names) {cJSON_free(entries);return 0;} + memset(entries,0,sizeof(char*)*numentries); + memset(names,0,sizeof(char*)*numentries); + + /* Collect all the results into our arrays: */ + child=item->child;depth++;if (fmt) len+=depth; + while (child) + { + names[i]=str=print_string_ptr(child->string,0); + entries[i++]=ret=print_value(child,depth,fmt,0); + if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1; + child=child->next; + } + + /* Try to allocate the output string */ + if (!fail) out=(char*)cJSON_malloc(len); + if (!out) fail=1; + + /* Handle failure */ + if (fail) + { + for (i=0;ichild;int i=0;while(c)i++,c=c->next;return i;} +cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;} +cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;} + +/* Utility for array list handling. */ +static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;} +/* Utility for handling references. */ +static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;} + +/* Add item to array/object. */ +void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}} +void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);} +void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);} +void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));} +void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));} + +cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0; + if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;} +void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));} +cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;} +void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));} + +/* Replace array/object items with new ones. */ +void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;} + newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;} +void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return; + newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem; + if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);} +void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}} + +/* Create basic types: */ +cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;} +cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;} +cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;} +cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;} +cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;} +cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;} +cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;} +cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;} + +/* Create Arrays: */ +cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} +cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && ichild=n;else suffix_object(p,n);p=n;}return a;} + +/* Duplication */ +cJSON *cJSON_Duplicate(cJSON *item,int recurse) +{ + cJSON *newitem,*cptr,*nptr=0,*newchild; + /* Bail on bad ptr */ + if (!item) return 0; + /* Create new item */ + newitem=cJSON_New_Item(); + if (!newitem) return 0; + /* Copy over all vars */ + newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble; + if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}} + if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}} + /* If non-recursive, then we're done! */ + if (!recurse) return newitem; + /* Walk the ->next chain for the child. */ + cptr=item->child; + while (cptr) + { + newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */ + if (!newchild) {cJSON_Delete(newitem);return 0;} + if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */ + else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */ + cptr=cptr->next; + } + return newitem; +} + +void cJSON_Minify(char *json) +{ + char *into=json; + while (*json) + { + if (*json==' ') json++; + else if (*json=='\t') json++; /* Whitespace characters. */ + else if (*json=='\r') json++; + else if (*json=='\n') json++; + else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments, to end of line. */ + else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */ + else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */ + else *into++=*json++; /* All other characters. */ + } + *into=0; /* and null-terminate. */ +} diff --git a/modules/saneui/cfg/cJSON.h b/modules/saneui/cfg/cJSON.h new file mode 100644 index 00000000..58b91ef6 --- /dev/null +++ b/modules/saneui/cfg/cJSON.h @@ -0,0 +1,154 @@ +/* + Copyright (c) 2009 Dave Gamble + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#ifndef cJSON__h +#define cJSON__h +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* cJSON Types: */ +#define cJSON_False 0 +#define cJSON_True 1 +#define cJSON_NULL 2 +#define cJSON_Number 3 +#define cJSON_String 4 +#define cJSON_Array 5 +#define cJSON_Object 6 + +#define cJSON_IsReference 256 +#define cJSON_StringIsConst 512 + + +typedef void *(*malloc_fnxx)(size_t sz); +typedef void (*free_fnxx)(void *ptr); + +/* The cJSON structure: */ +typedef struct cJSON { + struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */ + struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */ + + int type; /* The type of the item, as above. */ + + char *valuestring; /* The item's string, if type==cJSON_String */ + int valueint; /* The item's number, if type==cJSON_Number */ + double valuedouble; /* The item's number, if type==cJSON_Number */ + + char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */ +} cJSON; + +typedef struct cJSON_Hooks { + malloc_fnxx malloc_fn; + free_fnxx free_fn; +} cJSON_Hooks; + +/* Supply malloc, realloc and free functions to cJSON */ +extern void cJSON_InitHooks(cJSON_Hooks* hooks); + + +/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */ +extern cJSON *cJSON_Parse(const char *value); +/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */ +extern char *cJSON_Print(cJSON *item); +/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */ +extern char *cJSON_PrintUnformatted(cJSON *item); +/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */ +extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt); +/* Delete a cJSON entity and all subentities. */ +extern void cJSON_Delete(cJSON *c); + +/* Returns the number of items in an array (or object). */ +extern int cJSON_GetArraySize(cJSON *array); +/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */ +extern cJSON *cJSON_GetArrayItem(cJSON *array,int item); +/* Get item "string" from object. Case insensitive. */ +extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string); + +/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */ +extern const char *cJSON_GetErrorPtr(void); + +/* These calls create a cJSON item of the appropriate type. */ +extern cJSON *cJSON_CreateNull(void); +extern cJSON *cJSON_CreateTrue(void); +extern cJSON *cJSON_CreateFalse(void); +extern cJSON *cJSON_CreateBool(int b); +extern cJSON *cJSON_CreateNumber(double num); +extern cJSON *cJSON_CreateString(const char *string); +extern cJSON *cJSON_CreateArray(void); +extern cJSON *cJSON_CreateObject(void); + +/* These utilities create an Array of count items. */ +extern cJSON *cJSON_CreateIntArray(const int *numbers,int count); +extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count); +extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count); +extern cJSON *cJSON_CreateStringArray(const char **strings,int count); + +/* Append item to the specified array/object. */ +extern void cJSON_AddItemToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item); +extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */ +/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */ +extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item); +extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item); + +/* Remove/Detatch items from Arrays/Objects. */ +extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which); +extern void cJSON_DeleteItemFromArray(cJSON *array,int which); +extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string); +extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string); + +/* Update array items. */ +extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */ +extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem); +extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem); + +/* Duplicate a cJSON item */ +extern cJSON *cJSON_Duplicate(cJSON *item,int recurse); +/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will +need to be released. With recurse!=0, it will duplicate any children connected to the item. +The item->next and ->prev pointers are always zero on return from Duplicate. */ + +/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */ +extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated); + +extern void cJSON_Minify(char *json); + +/* Macros for creating things quickly. */ +#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull()) +#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue()) +#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse()) +#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b)) +#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n)) +#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s)) + +/* When assigning an integer value, it needs to be propagated to valuedouble too. */ +#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) +#define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val)) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/modules/saneui/cfg/gb_json.cpp b/modules/saneui/cfg/gb_json.cpp new file mode 100644 index 00000000..6b6e1de0 --- /dev/null +++ b/modules/saneui/cfg/gb_json.cpp @@ -0,0 +1,1879 @@ + +#include "gb_json.h" +#include +#include +#include + +#include "../../sdk/include/huagao/brand.h" + +#if defined(WIN32) || defined(_WIN64) +#define bzero(b, s) memset(b, 0, s) +#endif + + +namespace gb +{ + static std::vector split_with(const char* str, const char* splitor = "/") + { + std::vector 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; + } + static int load_mini_file(const char* file, std::string& cont) + { + FILE* src = fopen(file, "rb"); + if (src) + { + size_t size = 0; + char *buf = NULL; + + fseek(src, 0, SEEK_END); + size = ftell(src); + fseek(src, 0, SEEK_SET); + buf = new char[size + 4]; + memset(buf, 0, size + 4); + fread(buf, 1, size, src); + fclose(src); + cont = std::string(buf, size); + delete[] buf; + + return 0; + } + else + return errno; + } + + refer::refer() : ref_(1) + {} + refer::~refer() + {} + + long refer::add_ref(void) + { +#if defined(WIN32) || defined(_WIN64) + return InterlockedIncrement(&ref_); +#else + return ++ref_; +#endif + } + long refer::release(void) + { +#if defined(WIN32) || defined(_WIN64) + long ref = InterlockedDecrement(&ref_); +#else + long ref = --ref_; +#endif + + if (ref == 0) + delete this; + + return ref; + } + + + json::json(char* json_txt) : obj_(0), cur_child_(0), is_array_(false) + { + memset(&walk_head_, 0, sizeof(walk_head_)); + attach_text(json_txt); + } + json::~json() + { + memset(&walk_head_, 0, sizeof(walk_head_)); + 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(bool is_array) + { + cJSON* obj = is_array ? cJSON_CreateArray() : cJSON_CreateObject(); + + // bzero(obj, sizeof(*obj)); // cleared in constructor already ! + + return obj; + } + cJSON* json::create_element_with_name(const char* name) + { + cJSON* obj = json::create_element(); + + 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& 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) + { + cJSON* pr = (cJSON*)((DWORD_PTR)prev - (DWORD_PTR)&((cJSON*)0)->next); + pr->next = now; + now->prev = pr; + // *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 tree(split_with(path)); + + if(tree.empty()) + return NULL; + + if(!obj_) + { + if(!create) + return NULL; + + obj_ = json::create_element(); + 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_ = json::create_element(array); + 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)) + { + val->release(); + + 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& 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; + } + + int json::count() + { + if(!obj_ || !obj_->child) + return 0; + + cJSON* child = obj_->child; + int cnt = 0; + + while(child) + { + cnt++; + child = child->next; + } + + return cnt; + } + + + 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_ = json::create_element(true); + 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_ = json::create_element(true); + 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_ = json::create_element(true); + 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_ = json::create_element(true); + 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_ = json::create_element(true); + 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::change_key(const char* old_key, const char* new_key) + { + if (!obj_ || !new_key || *new_key == 0 || !old_key || *old_key == 0) + return false; + + cJSON** addr = NULL, + *ele = find(old_key, false, &addr); + + if (!ele) + return false; + + if (strlen(ele->string) < strlen(new_key)) + { + int l = strlen(new_key) + 4; + free(ele->string); + ele->string = (char*)malloc(l); + memset(ele->string, 0, l); + } + strcpy(ele->string, new_key); + + return true; + } + bool json::remove(const char* key) + { + if(!obj_) + return false; + + cJSON **addr = NULL, + *ele = find(key, false, &addr); + + if(ele) + { + bool cur_child = cur_child_ == obj_->child; + + if(addr) + *addr = ele->next; + if (cur_child_ == ele) + { + if (cur_child) + { + walk_head_.next = obj_->child; + cur_child_ = &walk_head_; + } + else + cur_child_ = ele->prev; + } + if (ele->prev) + ele->prev->next = ele->next; + if (ele->next) + ele->next->prev = ele->prev; + ele->prev = NULL; + ele->next = 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; + } +} + +namespace updater +{ + static std::string hg_model_from_pid(const char* pid) + { + if (strcmp(pid, "7823") == 0) + return "G200"; + + char m[] = { 'G', pid[0], '0', '0', 0}; + + return std::string(m) + " - " + pid; + } + static std::string hv_model_from_pid(const char* pid) + { + std::string m(""); + if (strcmp(pid, "1000") == 0) + m = "HW-1000NS"; + else if (strcmp(pid, "1002") == 0) + m = "HW-1000"; + else if (strcmp(pid, "7000") == 0) + m = "HW-7000NS"; + else if (strcmp(pid, "7002") == 0) + m = "HW-7000"; + else if (strcmp(pid, "7039") == 0) + m = "HW-7000NS"; + else + m = std::string("HW-") + pid; + + return m + " - " + pid; + } + static std::string lsc_model_from_pid(const char* pid) + { + if (strcmp(pid, "8200") == 0) + return "G42S - 8200"; + else + { + char m[] = {'G', pid[1], pid[2], 'S', 0}; + + return std::string(m) + " - " + pid; + } + } + static std::string scanner_chinese_name_2_model(const char* cn) + { + static const char* hg = "\345\215\216\351\253\230", + * hw = "\346\261\211\347\216\213", + * lsc = "\347\253\213\346\200\235\350\276\260", + * smy = "\346\211\253\346\217\217\344\273\252\342\200\224G", + * f = strstr(cn, hg); + std::string model(""); + std::string(* model_from_pid)(const char* pid) = nullptr; + + if (f == cn) + { + model = "HUAGOSCAN "; + model_from_pid = hg_model_from_pid;; + } + else if (strstr(cn, hw) == cn) + { + model = "Hanvon "; + model_from_pid = hv_model_from_pid;; + } + else if (strstr(cn, lsc) == cn) + { + model = "LANXUMSCAN "; + model_from_pid = lsc_model_from_pid;; + } + else + return ""; + + f = strstr(cn, smy); + if (!f) + return ""; + + f += strlen(smy); + model += model_from_pid(f); + + return model; + } + static int update_app_config(const char* scanner_name, const char* jsn_txt, const char* path, gb::scanner_cfg::LPUDF lpfunc) + { + std::string scanner(""), jsn_str(jsn_txt); + std::vector efiles; + + if ((unsigned char)scanner_name[0] > 0x7f) + scanner = scanner_chinese_name_2_model(scanner_name); + else + scanner = scanner_name; + + gb::json* jsn = new gb::json(); + int cur_sel = -1, ret = 0; + gb::scanner_cfg* cfg = nullptr; + if (!jsn->attach_text(&jsn_str[0])) + { + jsn->release(); + return EINVAL; + } + + if (jsn->first_child(jsn_str)) + { + gb::json* child = new gb::json(); + if (child->attach_text(&jsn_str[0])) + { + if (!child->get_value("cur_sel", cur_sel)) + ret = EINVAL; + } + if (ret == 0) + { + cfg = new gb::scanner_cfg(); + int ind = 0; + while (jsn->next_child(jsn_str)) + { + if (!child->attach_text(&jsn_str[0])) + { + ret = EINVAL; + break; + } + + std::string schm_name(""); + if (!child->get_value("scheme", schm_name)) + { + ret = EINVAL; + break; + } + + gb::json* items = nullptr; + if (!child->get_value("opts", items) || !items) + { + ret = EINVAL; + break; + } + + gb::sane_config_schm* schm = new gb::sane_config_schm(); + if (items->first_child(jsn_str)) + { + do + { + std::string name(""), val(""); + gb::json* item = new gb::json(); + if (item->attach_text(&jsn_str[0])) + { + if (item->get_value("name", name) && item->get_value("value", val)) + { + name = lpfunc->title2name(name.c_str(), lpfunc->func_param); + lpfunc->trans_number(name.c_str(), val, lpfunc->func_param); + schm->set_value(name.c_str(), val.c_str(), val.length()); + + val = ""; + item->get_value("extra", val); + if (val.length() && gb::load_mini_file(val.c_str(), val) == 0) + { + schm->set_value(name.c_str(), val.c_str(), val.length(), true); + item->get_value("extra", val); + efiles.push_back(val); + } + } + } + item->release(); + } while (items->next_child(jsn_str)); + } + items->release(); + + cfg->add_scheme(schm, schm_name.c_str()); + schm->release(); + if (ind++ == cur_sel) + cfg->select_scheme(schm_name.c_str()); + } + } + child->release(); + } + jsn->release(); + if (cfg) + { + if (ret == 0) + { + cfg->save((path + scanner + ".cfg").c_str()); + for (auto& v : efiles) + rename(v.c_str(), (v + "_bk").c_str()); + } + cfg->release(); + } + + return ret; + } +} +namespace gb +{ + std::string sane_config_schm::opt_data_appendix_("_data"); + + sane_config_schm::sane_config_schm(scanner_cfg* scanner) : jsn_(NULL), bkp_(NULL), in_setting_(false), scheme_name_("") + , scanner_(scanner) + { + char empty[8] = { "{}" }; + jsn_ = new gb::json(); + jsn_->attach_text(empty); + def_val_ = new gb::json(); + if (scanner_) + scanner_->add_ref(); + } + sane_config_schm::~sane_config_schm() + { + clear(); + def_val_->release(); + if (scanner_) + scanner_->release(); + } + + bool sane_config_schm::hex(unsigned char ch, unsigned char* val) + { + bool ret = true; + + if (ch >= '0' && ch <= '9') + ch -= '0'; + else if (ch >= 'a' && ch <= 'f') + ch = ch - 'a' + 10; + else if (ch >= 'A' && ch <= 'F') + ch = ch - 'A' + 10; + else + ret = false; + + if (ret && val) + { + *val &= 0x0f0; + *val |= ch; + } + + return ret; + } + bool sane_config_schm::hex_char(const char* data, unsigned char* val) + { + unsigned char v = 0; + bool ret = false; + + if (sane_config_schm::hex(*data++, &v)) + { + v <<= 4; + if (sane_config_schm::hex(*data++, &v)) + { + if (val) + *val = v; + + ret = true; + } + } + + return ret; + } + bool sane_config_schm::is_option_data(std::string& name) + { + size_t pos = name.find(sane_config_schm::opt_data_appendix_); + + if (pos != std::string::npos) + { + if (pos + sane_config_schm::opt_data_appendix_.length() == name.length()) + { + name.erase(pos); + + return true; + } + } + + return false; + } + + void sane_config_schm::clear() + { + if (jsn_) + jsn_->release(); + jsn_ = NULL; + if (bkp_) + bkp_->release(); + bkp_ = NULL; + // file_ = ""; + } + std::string sane_config_schm::to_hex_letter(const char* data, size_t bytes) + { + std::string hex(""); + const unsigned char* ptr = (const unsigned char*)data; + char buf[8] = { 0 }; + + for (size_t i = 0; i < bytes; ++i) + { + sprintf(buf, "%02X", ptr[i]); + hex += buf; + } + + return hex; + } + std::string sane_config_schm::from_hex_letter(const char* data, size_t bytes) + { + std::string stream(""); + + bytes /= 2; + for (size_t i = 0; i < bytes; ++i) + { + unsigned char ch = 0; + if (!sane_config_schm::hex_char(data, &ch)) + break; + stream.append(1, ch); + data += 2; + } + + return stream; + } + std::string sane_config_schm::default_value(const char* hex_title) + { + std::string val(""); + + def_val_->get_value(hex_title, val); + + return val; + } + + sane_config_schm* sane_config_schm::copy(void) + { + sane_config_schm *cp = new sane_config_schm(scanner_); + std::string val(jsn_->to_string(false)); + + cp->scheme_name_ = scheme_name_; + cp->file_ = file_; + cp->jsn_->attach_text(&val[0]); + cp->id_name_ = id_name_; + val = def_val_->to_string(false); + cp->def_val_->attach_text(&val[0]); + + return cp; + } + bool sane_config_schm::load_from_file(const char* file) + { + clear(); + + std::string cont(""); + + file_ = file; + if (gb::load_mini_file(file, cont)) + return false; + + return load_from_mem(cont.c_str()); + } + bool sane_config_schm::load_from_mem(const char* mem, bool in_b64) + { + gb::base64 b64; + std::string stream(in_b64 ? b64.decode(mem, strlen(mem)) : mem); + + clear(); + jsn_ = new gb::json(); + if (!jsn_->attach_text(&stream[0])) + { + jsn_->release(); + jsn_ = NULL; + + return false; + } + + return true; + } + bool sane_config_schm::save_to(const char* file) + { + bool ret = false; + std::string encode(to_text_stream()); + + if (!file || *file == 0) + file = file_.c_str(); + + if (encode.length()) + { + FILE* dst = fopen(file, "wb"); + + if (dst) + { + fwrite(encode.c_str(), 1, encode.length(), dst); + fclose(dst); + ret = true; + } + } + + return ret; + } + void sane_config_schm::set_default_value(int sn, const char* name, const char* val, size_t bytes) + { + id_name_[sn] = name; + def_val_->set_value(name, to_hex_letter(val, bytes).c_str()); + } + void sane_config_schm::copy_default_value(sane_config_schm* from) + { + if(from) + { + std::string t(from->def_val_->to_string(false)); + + id_name_ = from->id_name_; + def_val_->attach_text(&t[0]); + } + } + bool sane_config_schm::first_config(std::string& name, std::string& val) + { + bool ret = false; + std::string raw_v(""); + + if (jsn_ && jsn_->first_child(raw_v, &name)) + { + val = sane_config_schm::from_hex_letter(raw_v.c_str(), raw_v.length()); + + ret = true; + } + + return ret; + } + bool sane_config_schm::next_config(std::string& name, std::string& val) + { + bool ret = false; + std::string raw_v(""); + + if (jsn_ && jsn_->next_child(raw_v, &name)) + { + val = sane_config_schm::from_hex_letter(raw_v.c_str(), raw_v.length()); + + ret = true; + } + + return ret; + } + bool sane_config_schm::get_config(const char* name, std::string& val) + { + bool ret = jsn_ ? jsn_->get_value(name, val) : false; + + if(!ret && def_val_) + ret = def_val_->get_value(name, val); + + if(ret) + val = sane_config_schm::from_hex_letter(val.c_str(), val.length()); + + return ret; + } + void sane_config_schm::begin_setting(bool restore) + { + if (bkp_) + bkp_->release(); + bkp_ = jsn_; + in_setting_ = true; + jsn_ = new gb::json(); + if (!restore && bkp_) + { + std::string stream(bkp_->to_string(false)); + if(stream.length()) + jsn_->attach_text(&stream[0]); + } + } + void sane_config_schm::config_changed(const char* name, const char* val, size_t bytes, bool extra) + { + std::string hex_v(to_hex_letter(val, bytes)); + + if (extra) + { + jsn_->set_value((name + sane_config_schm::opt_data_appendix_).c_str(), hex_v.c_str()); + } + else + { + std::string def = default_value(name); + if (hex_v == def) + { + jsn_->remove(name); + jsn_->remove((name + sane_config_schm::opt_data_appendix_).c_str()); + } + else + jsn_->set_value(name, hex_v.c_str()); + } + } + void sane_config_schm::config_changed(int sn, const char* val, size_t bytes, bool extra) + { + std::string name(""); + + if (id_name_.count(sn)) + { + name = id_name_[sn]; + config_changed(name.c_str(), val, bytes, extra); + } + } + void sane_config_schm::remove_config(const char* name) + { + if (jsn_) + jsn_->remove(name); + } + void sane_config_schm::set_value(const char* name, const char* val, size_t bytes, bool extra) + { + std::string hex_v(to_hex_letter(val, bytes)); + + if (extra) + jsn_->set_value((name + sane_config_schm::opt_data_appendix_).c_str(), hex_v.c_str()); + else + jsn_->set_value(name, hex_v.c_str()); + } + bool sane_config_schm::has_changed(int* items) + { + if(items) + *items = jsn_ ? jsn_->count() : 0; + + if(!bkp_) + { + return false; + } + + std::map old; + std::string n(""), v(""); + if(bkp_->first_child(v, &n)) + { + do + { + old[n] = v; + }while(bkp_->next_child(v, &n)); + } + + if(jsn_->first_child(v, &n)) + { + do + { + if(old.count(n) == 0) + return true; + if(old[n]!=v) + return true; + + old.erase(n); + }while(jsn_->next_child(v, &n)); + } + + return old.size() > 0; + } + void sane_config_schm::end_setting(bool cancel) + { + if (in_setting_) + { + if (cancel) + { + jsn_->release(); + jsn_ = bkp_; + bkp_ = NULL; + } + else if (bkp_) + { + bkp_->release(); + bkp_ = NULL; + } + } + in_setting_ = false; + } + int sane_config_schm::id_from_name(const char* name) + { + for (const auto& v : id_name_) + { + if (v.second == name) + return v.first; + } + + return -1; + } + std::string sane_config_schm::to_text_stream(bool b64, bool with_ver) + { + if (jsn_) + { + if(with_ver) + { + char ver[40] = { 0 }; + sprintf(ver, "%u.%u", VERSION_MAIN, VERSION_SUB); + jsn_->set_value("ver", ver); + } + + std::string cont(jsn_->to_string(false)); + if (b64) + { + gb::base64 b64; + + cont = b64.encode(cont.c_str(), cont.length()); + } + + return cont; + } + else + return ""; + } + std::string sane_config_schm::get_version(void) + { + std::string ver(""); + + if (jsn_) + jsn_->get_value("ver", ver); + + return ver; + } + std::string sane_config_schm::get_scheme_name(void) + { + return scheme_name_; + } + void sane_config_schm::set_scheme_name(const char* name) + { + scheme_name_ = name ? name : ""; + } + void sane_config_schm::update(bool(* is_float)(int, void*), void* param, const char* (* t2n)(const char*), std::string* discard) + { + if (!jsn_) + return; + + std::string ver(get_version()), + name(""), + val(""); + int mv = atoi(ver.c_str()), + sv = ver.find("."); + bool changed = false; + char vs[40] = { 0 }; + + if (sv++ != -1) + sv = atoi(ver.c_str() + sv); + + // change title to name ... + if (mv <= 4 && sv < 30) + { + if (jsn_->first_child(val, &name)) + { + changed = true; + do + { + jsn_->change_key(name.c_str(), t2n(sane_config_schm::from_hex_letter(name.c_str(), name.length()).c_str())); + } while (jsn_->next_child(val, &name)); + } + } + + // fix float does not convert to SANE_Fixed bug in eldest version .... (discard them) + if (ver.empty()) + { + if (jsn_->first_child(val, &name)) + { + do + { + int id = id_from_name(name.c_str()); + if (id == -1 || is_float(id, param)) + { + jsn_->remove(name.c_str()); + if (discard) + *discard += name + "\r\n"; + changed = true; + } + } while (jsn_->next_child(val, &name)); + } + } + sprintf(vs, "%u.%u", VERSION_MAIN, VERSION_SUB); + jsn_->set_value("ver", vs); + + if (changed) + save_to(NULL); + } + + + + + /////////////////////////////////////////////////////////////////////////////////// + // scanner_cfg + std::string scanner_cfg::global_name_ = "global"; + std::string scanner_cfg::cur_sel_ = "cur"; + std::string scanner_cfg::default_setting_name_; + + scanner_cfg::scanner_cfg() : path_(""), scanner_name_(""), global_(new json()) + { + default_setting_name_ = QObject::tr("default_setting").toStdString(); + init_version(); + init_select(); + } + scanner_cfg::~scanner_cfg() + { + clear(); + global_->release(); + } + + bool scanner_cfg::update(const char* file, LPUDF func) + { + std::string cont(""), name(""), path(file); + int ret = gb::load_mini_file(file, cont); + base64 b64; + json *jsn = nullptr; + bool ok = true; + + if (ret) + return false; + else if (cont.empty()) + return true; + + cont = b64.decode(cont.c_str(), cont.length()); + jsn = new json(); + if (!jsn->attach_text(&cont[0])) + { + jsn->release(); + return false; + } + + cont = ""; + ret = path.rfind(PATH_SYMBOL[0]); + if (ret++ != std::string::npos) + path.erase(ret); + if (jsn->first_child(cont, &name)) + { + do + { + ok &= updater::update_app_config(name.c_str(), cont.c_str(), path.c_str(), func) == 0; + } while (jsn->next_child(cont, &name)); + } + jsn->release(); + if (ok) + rename(file, (std::string(file) + "_bk").c_str()); + + return true; + } + + void scanner_cfg::clear(void) + { + global_->set_value("ver", ""); + global_->set_value(scanner_cfg::cur_sel_.c_str(), -1); + + for (size_t i = 0; i < schemes_.size(); ++i) + schemes_[i].schm->release(); + schemes_.clear(); + scanner_name_ = ""; + } + void scanner_cfg::init_version(void) + { + char vstr[40] = { 0 }; + + sprintf(vstr, "%u.%u", VERSION_MAIN, VERSION_SUB); + global_->set_value("ver", vstr); + } + void scanner_cfg::init_select(void) + { + global_->set_value(scanner_cfg::cur_sel_.c_str(), -1); + } + void scanner_cfg::walk_sibling_schemes(cJSON* first) + { + if (!first) + return; + + cJSON* next = first->next; + std::string name(first->string ? first->string : ""), + cont(""); + CFGSCHM sch; + + first->next = nullptr; + cont = json::to_string(first, false); + if (name == scanner_cfg::global_name_) + { + global_->attach_text(&cont[0]); + } + else + { + sch.schm = new sane_config_schm(); + if (sch.schm->load_from_mem(cont.c_str(), false)) + { + sch.name = sane_config_schm::from_hex_letter(name.c_str(), name.length()); + sch.schm->set_scheme_name(sch.name.c_str()); + schemes_.push_back(sch); + } + else + sch.schm->release(); + } + + first->next = next; + walk_sibling_schemes(next); + } + + int scanner_cfg::load_file(const char* file) + { + std::string cont(""); + int ret = gb::load_mini_file(file, cont); + + if (ret == 0) + ret = load_mem(cont.c_str()); + + // if (ret == 0 && scanner_name_.empty()) + { + const char* name = strrchr(file, PATH_SYMBOL[0]); + if (name++ == nullptr) + name = file; + else + path_ = std::string(file, name - file); + + scanner_name_ = name; + ret = scanner_name_.rfind('.'); + if (ret != std::string::npos) + scanner_name_.erase(ret); + ret = 0; + } + + return ret; + } + int scanner_cfg::load_mem(const char* mem) + { + base64 b64; + std::string text(b64.decode(mem, strlen(mem))); + cJSON* root = cJSON_Parse(text.c_str()); + + if (!root) + { + FILE* dst = fopen((path_ + "err_cfg.txt").c_str(), "wb"); + fwrite(text.c_str(), 1, text.length(), dst); + fclose(dst); + return EINVAL; + } + + clear(); + walk_sibling_schemes(root->child); + cJSON_Delete(root); + + return 0; + } + int scanner_cfg::save(const char* file) + { + if (!file && path_.empty() && scanner_name_.empty()) + return EINVAL; + + std::string cont("{\"" + scanner_cfg::global_name_ + "\":"), + f(file ? file : path_ + scanner_name_ + ".cfg"), + v(""); + int sel = -1; + + if (!global_->get_value("ver", v) || v.empty()) + init_version(); + if (!global_->get_value(scanner_cfg::cur_sel_.c_str(), sel) || sel >= schemes_.size()) + init_select(); + + cont += global_->to_string(false); + for (auto& v: schemes_) + { + cont += ",\"" + sane_config_schm::to_hex_letter(v.name.c_str(), v.name.length()) + "\":"; + cont += v.schm->to_text_stream(false, false); + } + cont += "}"; + + base64 b64; + FILE* dst = fopen(f.c_str(), "wb"); + + if (!dst) + return errno; + + f = b64.encode(cont.c_str(), cont.length()); + fwrite(f.c_str(), 1, f.length(), dst); + fclose(dst); + + return 0; + } + + void scanner_cfg::get_all_schemes(std::vector& schemes) + { + schemes.push_back(scanner_cfg::default_setting_name_); + for (auto& v : schemes_) + schemes.push_back(v.name); + } + sane_config_schm* scanner_cfg::get_scheme(const char* scheme_name) + { + sane_config_schm* found = nullptr; + + if (scheme_name && *scheme_name) + { + std::vector::iterator it = std::find(schemes_.begin(), schemes_.end(), scheme_name); + if (it != schemes_.end()) + found = it->schm; + } + else + { + int ind = -1; + + global_->get_value(scanner_cfg::cur_sel_.c_str(), ind); + if (ind >= 0 && ind < schemes_.size()) + found = schemes_[ind].schm; + } + + if (found) + found->add_ref(); + + return found; + } + std::string scanner_cfg::get_current_scheme_name(void) + { + int ind = -1; + + global_->get_value(scanner_cfg::cur_sel_.c_str(), ind); + if (ind >= 0 && ind < schemes_.size()) + return schemes_[ind].name; + else + return scanner_cfg::default_setting_name_; + } + bool scanner_cfg::remove_scheme(const char* scheme_name) + { + std::vector::iterator it = std::find(schemes_.begin(), schemes_.end(), scheme_name); + + if (it != schemes_.end()) + { + int id = it - schemes_.begin(), + ind = -1; + + it->schm->release(); + schemes_.erase(it); + global_->get_value(scanner_cfg::cur_sel_.c_str(), ind); + if (ind == id) + global_->set_value(scanner_cfg::cur_sel_.c_str(), -1); + else if (ind > id) + global_->set_value(scanner_cfg::cur_sel_.c_str(), ind - 1); + + return true; + } + + return false; + } + void scanner_cfg::remove_all_schemes(void) + { + for(auto& v: schemes_) + v.schm->release(); + + schemes_.clear(); + } + bool scanner_cfg::select_scheme(const char* scheme_name) + { + std::vector::iterator it = scheme_name ? std::find(schemes_.begin(), schemes_.end(), scheme_name) : schemes_.end(); + + if (it == schemes_.end()) + global_->set_value(scanner_cfg::cur_sel_.c_str(), -1); + else + global_->set_value(scanner_cfg::cur_sel_.c_str(), (int)(it - schemes_.begin())); + + return true; + } + + sane_config_schm* scanner_cfg::copy_scheme(const char* cp_from_name) // for UI setting, call release() if not use anymore + { + if (!cp_from_name) + return nullptr; + else if (scanner_cfg::default_setting_name_ == cp_from_name) + return new sane_config_schm(); + else + { + std::vector::iterator it = std::find(schemes_.begin(), schemes_.end(), cp_from_name); + if (it == schemes_.end()) + return nullptr; + + std::string cont(it->schm->to_text_stream()); + sane_config_schm* schm = new sane_config_schm(); + schm->load_from_mem(cont.c_str()); + + return schm; + } + } + bool scanner_cfg::add_scheme(sane_config_schm* schm, const char* name) + { + CFGSCHM cs; + + cs.name = name ? name : schm->get_scheme_name(); + if(cs.name.empty() || cs.name == scanner_cfg::global_name_) + return false; + + if (std::find(schemes_.begin(), schemes_.end(), cs.name.c_str()) != schemes_.end()) + return false; + + cs.schm = schm; + + schemes_.push_back(cs); + schm->set_scheme_name(cs.name.c_str()); + schm->add_ref(); + + return true; + } + bool scanner_cfg::rename_scheme(const char* from, const char* to) + { + if (to && std::find(schemes_.begin(), schemes_.end(), to) != schemes_.end()) + return false; + + for(auto& v: schemes_) + { + if(v.name == from) + { + v.name = to; + v.schm->set_scheme_name(to); + return true; + } + } + + return false; + } +} diff --git a/modules/saneui/cfg/gb_json.h b/modules/saneui/cfg/gb_json.h new file mode 100644 index 00000000..ffc79d94 --- /dev/null +++ b/modules/saneui/cfg/gb_json.h @@ -0,0 +1,233 @@ +#pragma once + +#if defined(WIN32) || defined(_WIN64) +#include +#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 +#include +#include +#include + +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& 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& val); + + int count(void); + 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 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(int* items = nullptr); + 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 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& 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); + }; +}; diff --git a/modules/saneui/cutdialog.cpp b/modules/saneui/cutdialog.cpp new file mode 100644 index 00000000..ff701baa --- /dev/null +++ b/modules/saneui/cutdialog.cpp @@ -0,0 +1,464 @@ +#include "cutdialog.h" +#include "ui_cutdialog.h" +#include +#include +#include +#include "HGString.h" +#include "sane/sane_option_definitions.h" + +cutDialog::cutDialog(QWidget *parent) : + QWidget(parent), + ui(new Ui::cutDialog) +{ + ui->setupUi(this); + divisor = 8; + dpi = 1; + sizeType = 0; + paperWidth = 185; + h_w = 260.0/185.0; + sizeRate = 1; + paperHeight = paperWidth*h_w; + + this->setFixedSize(paperWidth,paperHeight); + setMouseTracking(true); + m_startPoint = QPoint(10,10); + m_endPoint = QPoint(50,50); + m_mouse_down = false; + + initAllCorner(); +} + +cutDialog::~cutDialog() +{ + delete ui; +} + +void cutDialog::setPaperSize(QString type, const int w) +{ + paperType = type; + + if (paperType == OPTION_VALUE_ZZCC_A3) h_w = 420.0 / 297.0; + else if (paperType == OPTION_VALUE_ZZCC_8K) h_w = 390.0 / 270.0; + else if (paperType == OPTION_VALUE_ZZCC_16K) h_w = 270.0 / 190.0; + else if (paperType == OPTION_VALUE_ZZCC_16KHX) h_w = 190.0 / 270.0; + else if (paperType == OPTION_VALUE_ZZCC_A4) h_w = 297.0 / 210.0; + else if (paperType == OPTION_VALUE_ZZCC_A4HX) h_w = 210.0 / 297.0; + else if (paperType == OPTION_VALUE_ZZCC_A5) h_w = 210.0 / 148.0; + else if (paperType == OPTION_VALUE_ZZCC_A5HX) h_w = 148.0 / 210.0; + else if (paperType == OPTION_VALUE_ZZCC_A6) h_w = 148.0 / 105.0; + else if (paperType == OPTION_VALUE_ZZCC_A6HX) h_w = 105.0 / 148.0; + else if (paperType == OPTION_VALUE_ZZCC_B4) h_w = 353.0 / 250.0; + else if (paperType == OPTION_VALUE_ZZCC_B5) h_w = 250.0 / 176.0; + else if (paperType == OPTION_VALUE_ZZCC_B5HX) h_w = 176.0 / 250.0; + else if (paperType == OPTION_VALUE_ZZCC_B6) h_w = 176.0 / 125.0; + else if (paperType == OPTION_VALUE_ZZCC_B6HX) h_w = 125.0 / 176.0; + else if (paperType == OPTION_VALUE_ZZCC_Letter) h_w = 279.0 / 216.0; + else if (paperType == OPTION_VALUE_ZZCC_LetterHX) h_w = 216.0 / 279.0; + else if (paperType == OPTION_VALUE_ZZCC_DoubleLetter) h_w = 559.0 / 216.0; + else if (paperType == OPTION_VALUE_ZZCC_LEGAL) h_w = 356.0 / 216.0; + else if (paperType == OPTION_VALUE_ZZCC_SLSJ) h_w = 560.0 / 270.0; + else if(paperType == OPTION_VALUE_ZZCC_ZDSMCC) h_w = 3307.0*2/2338; + else if(paperType == OPTION_VALUE_ZZCC_PPYSCC) { + if(dpi == 100.0) h_w = 1795.0/1189; + if(dpi == 150.0) h_w = 1795.0/1784; + if(dpi == 200.0) h_w = 3307.0/2338; + if(dpi == 240.0) h_w = 4308.0/2854; + if(dpi == 200.0) h_w = 5385.0/3567; + }; + + + if(type.contains("3")) divisor = 2; + else if (type.contains("4")) divisor = 4; + else if (type.contains("5")) divisor = 6; + else if (type.contains("6")) divisor = 8; + else divisor = 4; + paperWidth = w; + if(type.contains(StdStringToUtf8("横向").c_str())) + paperWidth = paperWidth*h_w*1.5; + double realW = paperWidth; + + if (paperType == OPTION_VALUE_ZZCC_A3 || paperType == OPTION_VALUE_ZZCC_A4HX) realRate = 297.0 / realW; + else if (paperType == OPTION_VALUE_ZZCC_A4 || paperType == OPTION_VALUE_ZZCC_A5HX) realRate = 210.0 / realW; + else if (paperType == OPTION_VALUE_ZZCC_A5 || paperType == OPTION_VALUE_ZZCC_A6HX) realRate = 148.0 / realW; + else if (paperType == OPTION_VALUE_ZZCC_A6) realRate = 105.0 / realW; + else if (paperType == OPTION_VALUE_ZZCC_16K) realRate = 190.0 / realW; + else if (paperType == OPTION_VALUE_ZZCC_8K || paperType == OPTION_VALUE_ZZCC_16KHX) realRate = 270.0 / realW; + else if (paperType == OPTION_VALUE_ZZCC_B4 || paperType == OPTION_VALUE_ZZCC_B5HX) realRate = 250.0 / realW; + else if (paperType == OPTION_VALUE_ZZCC_B5 || paperType == OPTION_VALUE_ZZCC_B6HX) realRate = 176.0 / realW; + else if (paperType == OPTION_VALUE_ZZCC_B6) realRate = 125.0 / realW; + else if (paperType == OPTION_VALUE_ZZCC_Letter) realRate = 216.0 / realW; + else if (paperType == OPTION_VALUE_ZZCC_LetterHX) realRate = 279.0 / realW; + else if (paperType == OPTION_VALUE_ZZCC_DoubleLetter) realRate = 216.0 / realW; + else if (paperType == OPTION_VALUE_ZZCC_LEGAL) realRate = 216.0 / realW; + else if (paperType == OPTION_VALUE_ZZCC_SLSJ) realRate = 270.0 / realW; + else if(paperType == OPTION_VALUE_ZZCC_ZDSMCC) realRate = 297.0/realW; + else if(paperType == OPTION_VALUE_ZZCC_PPYSCC) { + if(dpi == 100.0) realRate = 1189.0*0.039377/dpi/realW; + if(dpi == 150.0) realRate = 1784*0.039377/dpi/realW; + if(dpi == 200.0) realRate = 2338*0.039377/dpi/realW; + if(dpi == 240.0) realRate = 2854*0.039377/dpi/realW; + if(dpi == 200.0) realRate = 3567*0.039377/dpi/realW; + }; + + paperHeight = paperWidth*h_w; + this->setFixedSize(paperWidth+4,paperHeight+4); + scaleRec = QRectF(0,0,paperWidth,paperHeight+0.5); + m_rect = QRectF(m_startPoint,m_endPoint); + update(); + refreshView(); +} + +void cutDialog::setDpiValue(const double d) +{ + dpi = d; + if(sizeType == PIXEL) sizeRate = 0.03937*dpi; + update(); +} + +void cutDialog::setSizeType(const SIZETYPE &t) +{ + sizeType = t; + switch (sizeType) { + case MILLIM: + sizeRate = 1; + break; + case INCH: + sizeRate = 0.03937; + break; + case PIXEL: + sizeRate = 0.03937*dpi; + break; + } + update(); +} + +void cutDialog::setCutRectWidth(double w) +{ + m_endPoint.setX(m_startPoint.x()+scaleRec.width()*w/getPaperSize().width()); + update(); +} + +void cutDialog::setCutRectHeight(double h) +{ + m_endPoint.setY(m_startPoint.y()+scaleRec.height()*h/getPaperSize().height()); + update(); +} + +void cutDialog::setCutRectStartX(double x) +{ + m_startPoint.setX(scaleRec.width()*x/getPaperSize().width()); + update(); +} + +void cutDialog::setCutRectStartY(double y) +{ + m_startPoint.setY(scaleRec.height()*y/getPaperSize().height()); + update(); +} + +QSizeF cutDialog::getPaperSize() const +{ + double realW = paperWidth*realRate*sizeRate; + double realH = paperHeight*realRate*sizeRate; + return QSizeF(realW,realH); +} + +QSizeF cutDialog::getCutRectSize() const +{ + double realCutW = getPaperSize().width()*m_rect.width()/scaleRec.width(); + double realCutH = getPaperSize().height()*m_rect.height()/scaleRec.height(); + return QSizeF(realCutW,realCutH); +} + +QPointF cutDialog::getCutRectStartPos() const +{ + double realCutX = getPaperSize().width()*m_startPoint.x()/scaleRec.width(); + double realCutY = getPaperSize().height()*m_startPoint.y()/scaleRec.height(); + return QPointF(realCutX,realCutY); +} + +QRectF cutDialog::getCutRectPixel() const +{ + double x = 0.03937*dpi*paperWidth*realRate*m_startPoint.x()/scaleRec.width(); + double y = 0.03937*dpi*paperHeight*realRate*m_startPoint.y()/scaleRec.height(); + double w = 0.03937*dpi*paperWidth*realRate*m_rect.width()/scaleRec.width(); + double h = 0.03937*dpi*paperHeight*realRate*m_rect.height()/scaleRec.height(); + return QRectF(x,y,w,h); +} + +void cutDialog::setCutRectPixel(QRectF &rect) +{ + m_startPoint.setX(scaleRec.width()*rect.x()/(paperWidth*realRate*0.03937*dpi)); + m_startPoint.setY(scaleRec.height()*rect.y()/(paperHeight*realRate*0.03937*dpi)); + m_endPoint.setX(m_startPoint.x()+scaleRec.width()*rect.width()/(paperWidth*realRate*0.03937*dpi)); + m_endPoint.setY(m_startPoint.y()+scaleRec.height()*rect.height()/(paperHeight*realRate*0.03937*dpi)); + update(); +} + +int cutDialog::getCutRectRight() const +{ + return getPaperSize().width()*m_rect.right()/scaleRec.right(); +} + +int cutDialog::getCutRectBottom() const +{ + return getPaperSize().height()*m_rect.bottom()/scaleRec.bottom(); +} + +void cutDialog::mousePressEvent(QMouseEvent *event) +{ + int x = event->x()/**paperWidth/width()*/; + int y = event->y()/**paperHeight/height()*/; + m_moveStart = QPoint(x,y); + m_mouse_down = event->button() == Qt::LeftButton; + update(); +} + +void cutDialog::mouseMoveEvent(QMouseEvent *event) +{ + int x = event->x()/**paperWidth/width()*/; + int y = event->y()/**paperHeight/height()*/; + if(m_mouse_down){ + int dx = m_moveStart.x() - x; + int dy = m_moveStart.y() - y; + m_moveStart = QPoint(x,y); + + if(m_leftCorn){ + m_startPoint.setX(x); + }else if(m_rightCorn){ + m_endPoint.setX(x); + }else if(m_topCorn){ + m_startPoint.setY(y); + }else if(m_bottomCorn){ + m_endPoint.setY(y); + }else if(m_leftTop){ + m_startPoint.setX(x); + m_startPoint.setY(y); + }else if(m_leftBottom){ + m_startPoint.setX(x); + m_endPoint.setY(y); + }else if(m_rightTop){ + m_startPoint.setY(y); + m_endPoint.setX(x); + }else if(m_rightBottom){ + m_endPoint.setX(x); + m_endPoint.setY(y); + } + else if(!m_out){ + if(m_startPoint.x() - dx < 0) dx = 0; + if(m_startPoint.y() - dy < 0) dy = 0; + if(m_endPoint.x() - dx > scaleRec.right()) dx = 0; + if(m_endPoint.y() - dy > scaleRec.bottom()) dy = 0; + m_startPoint.setX(m_rect.left()-dx); + m_startPoint.setY(m_rect.top()-dy); + m_endPoint.setX(m_rect.right()-dx); + m_endPoint.setY(m_rect.bottom()-dy); + } + if(m_startPoint.x()<=0) m_startPoint.setX(0); + if(m_startPoint.y()<=0) m_startPoint.setY(0); + if(m_endPoint.x()>=scaleRec.width()) m_endPoint.setX(scaleRec.right()); + if(m_endPoint.y()>=scaleRec.height()) m_endPoint.setY(scaleRec.bottom()); + + + if(qAbs(m_startPoint.x() - m_endPoint.x()) <= 10 || m_startPoint.x() > m_endPoint.x()){ + m_startPoint.setX(m_rect.left()); + m_endPoint.setX(m_rect.right()); + } + if(qAbs(m_startPoint.y() - m_endPoint.y()) <= 10 || m_startPoint.y() > m_endPoint.y()){ + m_startPoint.setY(m_rect.top()); + m_endPoint.setY(m_rect.bottom()); + } + + update(); + }else{ + mousePosition(QPoint(x,y)); + } +} + +void cutDialog::mouseReleaseEvent(QMouseEvent *) +{ + m_mouse_down = false; + update(); +} + +void cutDialog::enterEvent(QEvent *) +{ + emit lineEditEnable(false); +} + +void cutDialog::leaveEvent(QEvent *) +{ + emit lineEditEnable(true); +} + +void cutDialog::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.translate(0,0); + + drawScale(painter); + drawCutRect(painter); + drawTransparentColor(painter); + if(m_mouse_down){ + if(sizeType == INCH || sizeType == MILLIM){ + emit cutRectX(QString::number(getCutRectStartPos().x(),'f',2).toDouble()); + emit cutRectY(QString::number(getCutRectStartPos().y(),'f',2).toDouble()); + emit cutRectWidth(QString::number(getCutRectSize().width(),'f',2).toDouble()); + emit cutRectHeight(QString::number(getCutRectSize().height(),'f',2).toDouble()); + }else{ + emit cutRectX(double(int(getCutRectStartPos().x()))); + emit cutRectY(double(int(getCutRectStartPos().y()))); + emit cutRectWidth(double(int(getCutRectSize().width()))); + emit cutRectHeight(double(int(getCutRectSize().height()))); + } + } + + painter.end(); +} + +void cutDialog::drawScale(QPainter& painter) +{ + painter.setPen(QPen(Qt::black,1)); + scaleRec = QRectF(0,0,paperWidth,paperHeight+0.5); + painter.drawRect(scaleRec); + for(int i = 6 ; i <= paperWidth-6; i++){ + if(int(paperWidth/2) == i || int(paperWidth/4) == i || int(paperWidth*3/4) == i){ + painter.setPen(QPen(Qt::gray,1)); + painter.drawLine(i,0,i,paperHeight); + painter.setPen(QPen(Qt::black,1)); + } + if(i%divisor == 0){ + painter.drawLine(i,paperHeight-4,i,paperHeight); + painter.drawLine(i,0,i,4); + } + if(i%(divisor*5) == 0){ + painter.drawLine(i,paperHeight-8,i,paperHeight); + painter.drawLine(i,0,i,8); + } + } + for(int i = 6 ; i <= paperHeight-6; i++){ + if(int(paperHeight/2) == i || int(paperHeight/4) == i || int(paperHeight*3/4) == i){ + painter.setPen(QPen(Qt::gray,1)); + painter.drawLine(0,i,paperWidth,i); + painter.setPen(QPen(Qt::black,1)); + } + if(i%divisor == 0){ + painter.drawLine(0,i,4,i); + painter.drawLine(paperWidth,i,paperWidth-4,i); + } + if(i%(divisor*5) == 0){ + painter.drawLine(0,i,8,i); + painter.drawLine(paperWidth,i,paperWidth-8,i); + } + } +} + +void cutDialog::drawCutRect(QPainter &painter) +{ + painter.setPen(QPen(Qt::green,1)); + m_rect = QRectF(m_startPoint,m_endPoint); + + QRectF r(m_rect); + if(r.right() + 6 > paperWidth) + r.setRight(paperWidth - 6); + if(r.bottom() + 2 > paperHeight) + r.setBottom(paperHeight - 2); + + painter.drawRect(r); + painter.setPen(QPen(Qt::red,1)); + painter.setBrush(Qt::red); + painter.drawEllipse(r.left()-2,(r.bottom()-r.top())/2+r.top()-2,4,4); + painter.drawEllipse(r.left()-2,r.top()-2,4,4); + painter.drawEllipse(r.left()-2,r.bottom()-2,4,4); + painter.drawEllipse(r.right()-2,r.top()-2,4,4); + painter.drawEllipse(r.right()-2,r.bottom()-2,4,4); + painter.drawEllipse(r.right()-2,(r.bottom()-r.top())/2+r.top()-2,4,4); + painter.drawEllipse((r.right()-r.left())/2+r.left()-2,r.top()-2,4,4); + painter.drawEllipse((r.right()-r.left())/2+r.left()-2,r.bottom()-2,4,4); +} + +void cutDialog::drawTransparentColor(QPainter &painter) +{ + QPainterPath painterPath; + QPainterPath p; + p.addRect(scaleRec); + painterPath.addRect(m_rect); + QPainterPath drawPath =p.subtracted(painterPath); + painter.setOpacity(0.7); + painter.fillPath(drawPath,QBrush(Qt::gray)); +} + +void cutDialog::mousePosition(const QPoint& e) +{ + initAllCorner(); + QRectF r = QRectF(m_rect); + int x = e.x(); + int y = e.y(); + m_left = qAbs(x - r.left()) < 5; + m_right = qAbs(x - r.right()) < 5; + m_bottom = qAbs(y - r.bottom()) < 5; + m_top = qAbs(y - r.top()) < 5; + m_out = r.left()-x>=5 || x-r.right()>=5 || r.top()-y>=5 || y-r.bottom()>=5; + bool lorr = m_left | m_right; + bool torb = m_top | m_bottom; + if(lorr && torb) + { + if((m_left && m_top) || (m_right && m_bottom)) + setCursor(Qt::SizeFDiagCursor); + else + setCursor(Qt::SizeBDiagCursor); + } + else if(lorr) + setCursor(Qt::SizeHorCursor); + else if(torb) + setCursor(Qt::SizeVerCursor); + else if(!m_out) + { + setCursor(Qt::SizeAllCursor); + m_bottom = m_left = m_right = m_top = false; + }else if(m_out){ + setCursor(Qt::ArrowCursor); + m_bottom = m_left = m_right = m_top = false; + } + + if(m_left && m_top) m_leftTop = true; + else if(m_left && m_bottom) m_leftBottom = true; + else if(m_right && m_top) m_rightTop = true; + else if(m_right && m_bottom) m_rightBottom = true; + else if(m_left && !m_top && !m_bottom) m_leftCorn = true; + else if(m_right && !m_top && !m_bottom) m_rightCorn = true; + else if(m_top && !m_left && !m_right) m_topCorn = true; + else if(m_bottom && !m_left && !m_right) m_bottomCorn = true; + else initAllCorner(); +} + +void cutDialog::refreshView() +{ + if(sizeType == INCH){ + emit cutRectX(QString::number(getCutRectStartPos().x(),'f',2).toDouble()); + emit cutRectY(QString::number(getCutRectStartPos().y(),'f',2).toDouble()); + emit cutRectWidth(QString::number(getCutRectSize().width(),'f',2).toDouble()); + emit cutRectHeight(QString::number(getCutRectSize().height(),'f',2).toDouble()); + }else{ + emit cutRectX(QString::number(getCutRectStartPos().x(),'f',0).toDouble()); + emit cutRectY(QString::number(getCutRectStartPos().y(),'f',0).toDouble()); + emit cutRectWidth(double(int(getCutRectSize().width()))); + emit cutRectHeight(double(int(getCutRectSize().height()))); + } +} + +void cutDialog::initAllCorner() +{ + m_left = false; + m_right = false; + m_bottom = false; + m_top = false; + m_leftCorn = false; + m_rightCorn = false; + m_topCorn = false; + m_bottomCorn = false; + m_leftTop = false; + m_leftBottom = false; + m_rightTop = false; + m_rightBottom = false; +} diff --git a/modules/saneui/cutdialog.h b/modules/saneui/cutdialog.h new file mode 100644 index 00000000..2f77ef2a --- /dev/null +++ b/modules/saneui/cutdialog.h @@ -0,0 +1,100 @@ +#ifndef CUTDIALOG_H +#define CUTDIALOG_H + +#include +#include +#include +#include + +namespace Ui { +class cutDialog; +} + +enum SIZETYPE{ + MILLIM , + INCH, + PIXEL +}; + +class cutDialog : public QWidget +{ + Q_OBJECT + +public: + explicit cutDialog(QWidget *parent = nullptr); + ~cutDialog(); + void setPaperSize(QString type = "A1", const int w = 200); + void setDpiValue(const double d); + void setSizeType(const SIZETYPE& t); + void setCutRectWidth(double w); + void setCutRectHeight(double h); + void setCutRectStartX(double x); + void setCutRectStartY(double y); + QSizeF getPaperSize()const; + QSizeF getCutRectSize()const; + QPointF getCutRectStartPos()const; + QRectF getCutRectPixel()const; + void setCutRectPixel(QRectF& rect); + int getCutRectRight()const; + int getCutRectBottom()const; + void refreshView(); + +signals: + void cutRectX(double x); + void cutRectY(double y); + void cutRectWidth(double w); + void cutRectHeight(double h); + void lineEditEnable(bool b); + +private: + void mousePressEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void enterEvent(QEvent*); + void leaveEvent(QEvent*); + //void resizeEvent(QResizeEvent*); + void paintEvent(QPaintEvent *); + void drawScale(QPainter &painter); + void drawCutRect(QPainter &painter); + void drawTransparentColor(QPainter &painter); + void drawPaperSize(); + void mousePosition(const QPoint &e); + void initAllCorner(); + //void mouseChangeRect(int dx,int dy); + +private: + Ui::cutDialog *ui; + QPointF m_startPoint; + QPointF m_endPoint; + QPointF m_moveStart; + + QRectF m_rect; + QRectF scaleRec; + + QString paperType; + double paperWidth; + double paperHeight; + int divisor; + int sizeType; + double dpi; + double h_w; + double realRate; + double sizeRate; + + bool m_mouse_down; + bool m_left; + bool m_right; + bool m_bottom; + bool m_top; + bool m_leftCorn; + bool m_rightCorn; + bool m_topCorn; + bool m_bottomCorn; + bool m_leftTop; + bool m_rightTop; + bool m_leftBottom; + bool m_rightBottom; + bool m_out; +}; + +#endif // CUTDIALOG_H diff --git a/modules/saneui/cutdialog.ui b/modules/saneui/cutdialog.ui new file mode 100644 index 00000000..de03c34e --- /dev/null +++ b/modules/saneui/cutdialog.ui @@ -0,0 +1,44 @@ + + + cutDialog + + + true + + + + 0 + 0 + 321 + 342 + + + + + 0 + 0 + + + + + 2 + 0 + + + + + 2 + 0 + + + + true + + + cutDialog + + + + + + diff --git a/modules/saneui/cutpapertool.cpp b/modules/saneui/cutpapertool.cpp new file mode 100644 index 00000000..ab2f84e0 --- /dev/null +++ b/modules/saneui/cutpapertool.cpp @@ -0,0 +1,219 @@ +#include "cutpapertool.h" +#include "ui_cutpapertool.h" +#include +#include + +CutPaperTool::CutPaperTool(QWidget *parent) : + QDialog(parent), + ui(new Ui::CutPaperTool) +{ + ui->setupUi(this); + setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); + connect(ui->widget,SIGNAL(cutRectX(double)),this,SLOT(cutRectXSlot(double))); + connect(ui->widget,SIGNAL(cutRectY(double)),this,SLOT(cutRectYSlot(double))); + connect(ui->widget,SIGNAL(cutRectWidth(double)),this,SLOT(cutRectWidthSlot(double))); + connect(ui->widget,SIGNAL(cutRectHeight(double)),this,SLOT(cutRectHeightSlot(double))); + connect(ui->widget,SIGNAL(lineEditEnable(bool)),this,SLOT(lineEditEnableSlot(bool))); + //setDpi(200); + //setPaperType(200,"A4",400); + ui->widget->setSizeType(MILLIM); + setSizeLabel(); + //ui->pbtn_init->setFixedWidth(160); + this->setFixedWidth(ui->widget->width()+40); +} + +CutPaperTool::~CutPaperTool() +{ + delete ui; +} + +void CutPaperTool::paintEvent(QPaintEvent *) +{ + +} + +void CutPaperTool::setPaperType(const int d, const QString &t, const int& w) +{ + dpi = d; + ui->dpiLab->setText(QString::number(dpi)); + ui->widget->setDpiValue(dpi); + paperType = t; + ui->paperLab->setText(paperType); + ui->widget->setPaperSize(paperType,w); + //ui->widget->refreshView(); + setSizeLabel(); + this->setFixedWidth(ui->widget->width()+40); + setSizeInit(); +} + +QRectF CutPaperTool::getCutRectPixel() +{ + return QRectF(ui->widget->getCutRectPixel()); +} + +void CutPaperTool::setCutRect(QRectF &rect) +{ + ui->widget->setCutRectPixel(rect); + ui->startXEdt->setText(QString::number(rect.x()/dpi/0.03937)); + ui->startYEdt->setText(QString::number(rect.y()/dpi/0.03937)); + ui->rectWidth->setText(QString::number(rect.width()/dpi/0.03937)); + ui->rectHeight->setText(QString::number(rect.height()/dpi/0.03937)); +} + +void CutPaperTool::setSizeLabel() +{ + QString wSize; + QString hSize; + if(ui->comboBox_2->currentIndex() == INCH){ + wSize = QString::number(ui->widget->getPaperSize().width(),'f',2); + hSize = QString::number(ui->widget->getPaperSize().height(),'f',2); + } + else { + wSize = QString::number(int(ui->widget->getPaperSize().width()+0.001)); + hSize = QString::number(int(ui->widget->getPaperSize().height()+0.001)); + } + ui->sizeLabel->setText("("+wSize + " * " +hSize+")"); +} + +void CutPaperTool::setSizeInit() +{ + ui->widget->setCutRectStartX(0); + ui->widget->setCutRectStartY(0); + ui->widget->setCutRectWidth(ui->widget->getPaperSize().width()); + ui->widget->setCutRectHeight(ui->widget->getPaperSize().height()); + ui->startXEdt->setText("0"); + ui->startYEdt->setText("0"); + ui->rectWidth->setText(QString::number(int(ui->widget->getPaperSize().width()))); + ui->rectHeight->setText(QString::number(int(ui->widget->getPaperSize().height()))); +} + +void CutPaperTool::setSizeInit(QRectF& rect){ + setSizeInit(); + if(rect != QRectF(0,0,0,0)) + setCutRect(rect); +} + +void CutPaperTool::cutRectXSlot(double x) +{ + ui->startXEdt->setText(QString::number(x)); +} + +void CutPaperTool::cutRectYSlot(double y) +{ + ui->startYEdt->setText(QString::number(y)); +} + +void CutPaperTool::cutRectWidthSlot(double w) +{ + ui->rectWidth->setText(QString::number(w)); +} + +void CutPaperTool::cutRectHeightSlot(double h) +{ + ui->rectHeight->setText(QString::number(h)); +} + +void CutPaperTool::lineEditEnableSlot(bool b) +{ + ui->startXEdt->setEnabled(b); + ui->startYEdt->setEnabled(b); + ui->rectWidth->setEnabled(b); + ui->rectHeight->setEnabled(b); +} + +void CutPaperTool::on_startXEdt_textEdited(QString arg1) +{ + double x = arg1.toDouble(); + if(x >ui->widget->getCutRectRight()) { + //arg1.chop(1); + //x = arg1.toDouble(); + //x = ui->widget->getCutRectRight(); + return ; + } + if(type == PIXEL) x = arg1.toInt(); + ui->widget->setCutRectStartX(x); +} + +void CutPaperTool::on_startYEdt_textEdited(QString arg1) +{ + double y = arg1.toDouble(); + if(y >ui->widget->getCutRectBottom()) { + //arg1.chop(1); + //y = arg1.toDouble(); + return ; + } + if(type == PIXEL) y = arg1.toInt(); + ui->widget->setCutRectStartY(y); +} + +void CutPaperTool::on_rectWidth_textEdited(QString arg1) +{ + double v = arg1.toDouble(); + if(v > ui->widget->getPaperSize().width() - ui->widget->getCutRectStartPos().x()) { + //arg1.chop(1); + //v = arg1.toDouble(); + //v=ui->widget->getPaperSize().width() - ui->widget->getCutRectStartPos().x(); + return ; + } + if(type == PIXEL) v = arg1.toInt(); + ui->widget->setCutRectWidth(v); +} + +void CutPaperTool::on_rectHeight_textEdited(QString arg1) +{ + double v = arg1.toDouble(); + if(v > ui->widget->getPaperSize().height() - ui->widget->getCutRectStartPos().y()) { + //arg1.chop(1); + //v = arg1.toDouble(); + //v = ui->widget->getPaperSize().height() - ui->widget->getCutRectStartPos().y(); + return ; + } + if(type == PIXEL) v = arg1.toInt(); + ui->widget->setCutRectHeight(v); +} + +void CutPaperTool::on_comboBox_2_currentIndexChanged(int index) +{ + switch(index){ + case 0: + ui->xLabel->setText("mm"); + ui->yLabel->setText("mm"); + ui->wLabel->setText("mm"); + ui->hLabel->setText("mm"); + ui->widget->setSizeType(MILLIM); + break; + case 1: + ui->xLabel->setText("in"); + ui->yLabel->setText("in"); + ui->wLabel->setText("in"); + ui->hLabel->setText("in"); + ui->widget->setSizeType(INCH); + break; + case 2: + ui->xLabel->setText("px"); + ui->yLabel->setText("px"); + ui->wLabel->setText("px"); + ui->hLabel->setText("px"); + ui->widget->setSizeType(PIXEL); + break; + } + update(); + setSizeLabel(); + ui->widget->refreshView(); +} + + +void CutPaperTool::on_buttonBox_accepted() +{ + accept(); +} + +void CutPaperTool::on_buttonBox_rejected() +{ + reject(); +} + +void CutPaperTool::on_pbtn_init_clicked() +{ + setSizeInit(); +} diff --git a/modules/saneui/cutpapertool.h b/modules/saneui/cutpapertool.h new file mode 100644 index 00000000..cf6d40eb --- /dev/null +++ b/modules/saneui/cutpapertool.h @@ -0,0 +1,59 @@ +#ifndef CUTPAPERTOOL_H +#define CUTPAPERTOOL_H + +#include +#include "cutdialog.h" + +namespace Ui { +class CutPaperTool; +} + +class CutPaperTool : public QDialog +{ + Q_OBJECT + +public: + explicit CutPaperTool(QWidget *parent = nullptr); + ~CutPaperTool(); + void setPaperType(const int dpi, const QString& t,const int& w=200); + QRectF getCutRectPixel(); + void setCutRect(QRectF& rect); + void setSizeInit(); + void setSizeInit(QRectF& rect); + + +private: + void paintEvent(QPaintEvent *); + void setSizeLabel(); + +private slots: + void cutRectXSlot(double x); + void cutRectYSlot(double y); + void cutRectWidthSlot(double w); + void cutRectHeightSlot(double h); + void lineEditEnableSlot(bool b); + + void on_startXEdt_textEdited(QString arg1); + + void on_startYEdt_textEdited(QString arg1); + + void on_rectWidth_textEdited(QString arg1); + + void on_rectHeight_textEdited(QString arg1); + + void on_comboBox_2_currentIndexChanged(int index); + + void on_buttonBox_accepted(); + + void on_buttonBox_rejected(); + + void on_pbtn_init_clicked(); + +private: + Ui::CutPaperTool *ui; + SIZETYPE type; + int dpi; + QString paperType; +}; + +#endif // CUTPAPERTOOL_H diff --git a/modules/saneui/cutpapertool.ui b/modules/saneui/cutpapertool.ui new file mode 100644 index 00000000..0e5178d6 --- /dev/null +++ b/modules/saneui/cutpapertool.ui @@ -0,0 +1,298 @@ + + + CutPaperTool + + + true + + + + 0 + 0 + 439 + 676 + + + + + 0 + 0 + + + + 自定义扫描区域 + + + + + + + + 纸张尺寸: + + + + + + + A4 + + + + + + + (210*297) + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + DPI(像素/英寸): + + + Qt::AlignJustify|Qt::AlignVCenter + + + + + + + 200 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 单位: + + + + + + + + 毫米(mm) + + + + + 英寸(in) + + + + + 像素(px) + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 初始化选择区域 + + + + + + + + + true + + + + + 0 + 0 + 421 + 430 + + + + + + + + 0 + 0 + + + + + + + + + + + + + + x: + + + + + + + + + + mm + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + y: + + + + + + + + + + mm + + + + + + + + + + + w: + + + + + + + + + + mm + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + h: + + + + + + + + + + mm + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + cutDialog + QWidget +
cutdialog.h
+ 1 +
+
+ + +
diff --git a/modules/saneui/device_menu.cpp b/modules/saneui/device_menu.cpp new file mode 100644 index 00000000..1259f158 --- /dev/null +++ b/modules/saneui/device_menu.cpp @@ -0,0 +1,189 @@ +#include "device_menu.h" + +#define ACTION_DEVICE_NAME_PROPERTY "device_name" + +device_menu::device_menu(QWidget *parent) + : QMenu(parent) + , cur_action_(nullptr), none_action_(nullptr) +{ + group_action_ = new QActionGroup(this); + deviceMenuUpdate(nullptr); + connect(group_action_, SIGNAL(triggered(QAction*)), this, SLOT(on_act_triggered(QAction*))); +} + +device_menu::device_menu(const QString &title, QWidget *parent) + : QMenu(title, parent) + , cur_action_(nullptr), none_action_(nullptr) +{ + group_action_ = new QActionGroup(this); + deviceMenuUpdate(nullptr); + connect(group_action_, SIGNAL(triggered(QAction*)), this, SLOT(on_act_triggered(QAction*))); +} + +QMenu* device_menu::find_device_menu(const QString& dev_name) +{ + std::lock_guard lock(mutex_); + std::vector::iterator it = std::find(menus_.begin(), menus_.end(), dev_name); + + if(it == menus_.end()) + return nullptr; + else + return it->menu; +} +QAction* device_menu::find_device_config(const QString& dev_name, const QString& cfg_name) +{ + std::lock_guard lock(mutex_); + std::vector::iterator it = std::find(menus_.begin(), menus_.end(), dev_name); + + if(it == menus_.end()) + return NULL; + + for(size_t i = 0; i < it->actions.size(); ++i) + { + if(it->actions[i]->text() == cfg_name) + return it->actions[i]; + } + + return NULL; +} + +void device_menu::connectedDevice(const QString &device) +{ + QMenu* menu = find_device_menu(device); + if (menu) + menu->setEnabled(true); +} + +void device_menu::disconnectedDevice(const QString &device) +{ + QMenu* menu = find_device_menu(device); + if (menu) + menu->setEnabled(false); +} + +void device_menu::setOptionChecked(const QString &device, const QString &opt, bool checked) +{ + QAction* act = find_device_config(device, opt); + + if(act) + { + act->setChecked(checked); + if(checked) + cur_action_ = act; + else + { + if(cur_action_ == act) + cur_action_ = nullptr; + } + } + else if(checked) + cur_action_ = nullptr; +} + +void device_menu::get_online_devices(QList& dev_names) +{ + std::lock_guard lock(mutex_); + + for(size_t i = 0; i < menus_.size(); ++i) + { + if(menus_[i].menu->isEnabled()) + dev_names.push_back(menus_[i].menu->title()); + } +} + +void device_menu::deviceMenuUpdate(dev_que* que) +{ + std::lock_guard lock(mutex_); + + cur_action_ = nullptr; + if(none_action_) + { + removeAction(none_action_); + none_action_ = nullptr; + } + + for(size_t i = 0; i < menus_.size(); ++i) + menus_[i].menu->setEnabled(false); + if (!que || que->scanners() == 0) + { + if(menus_.empty()) + { + none_action_ = addAction(tr("no device")); + none_action_->setEnabled(false); + } + + return; + } + + for (size_t i = 0; i < que->scanners(); i++) + { + SCANNER s = que->get_at(i); + std::vector::iterator it = std::find(menus_.begin(), menus_.end(), QString::fromStdString((s.name))); + POPMENU pm; + std::vector schemes; + + if(it == menus_.end()) + pm.menu = addMenu(QString::fromStdString(s.name)); + else + { + pm = *it; + menus_.erase(it); + } + pm.menu->setEnabled(true); + pm.menu->setToolTipsVisible(true); + for(size_t j = 0; j < pm.actions.size(); ++j) + { + pm.menu->removeAction(pm.actions[j]); + group_action_->removeAction(pm.actions[j]); + } + pm.actions.clear(); + s.cfg->get_all_schemes(schemes); + for (size_t j = 0; j < schemes.size(); j++) + { + QAction *child = group_action_->addAction(QString::fromStdString(schemes[j])); + child->setProperty(ACTION_DEVICE_NAME_PROPERTY, QVariant(QString::fromStdString(s.name))); + child->setCheckable(true); + + if(que->opened_scanner_name() == s.name && + schemes[j] == s.cfg->get_current_scheme_name()) + { + cur_action_ = child; + child->setChecked(true); + } + + pm.menu->addAction(child); + pm.actions.push_back(child); + + QString tips; + if(tips.isNull()) + { + tips = tr("default setting"); + } + // child->setToolTip(tips); + } + menus_.push_back(pm); + s.cfg->release(); + } +} + +void device_menu::on_act_triggered(QAction* act) +{ + QString deviceName = act->property(ACTION_DEVICE_NAME_PROPERTY).toString(); + QString opt = act->text(); + bool checked_now = act->isChecked(); + + if(cur_action_ == act) + { + checked_now = false; + act->setChecked(false); + cur_action_ = nullptr; +// emit scanOptionsChanged("", "", false); +// return; + } + else { + cur_action_ = act; + checked_now = true; + } + + emit scanOptionsChanged(deviceName, opt, checked_now); +} diff --git a/modules/saneui/device_menu.h b/modules/saneui/device_menu.h new file mode 100644 index 00000000..6013871d --- /dev/null +++ b/modules/saneui/device_menu.h @@ -0,0 +1,494 @@ +#ifndef DEVICE_MENU_H +#define DEVICE_MENU_H + +#include +#include +#include "sane/sane_ex.h" +#include "sane/sane_option_definitions.h" +#include "../../../sdk/include/huagao/hgscanner_error.h" + +#include "cfg/gb_json.h" +#include "lang/app_language.h" + +typedef struct _scanner +{ + std::string name; + std::string model; + bool online; + gb::scanner_cfg *cfg; +}SCANNER; +class dev_que +{ + std::vector 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(SANEAPI* saneApi, SANE_Handle h, gb::sane_config_schm* schm) + { + SANE_Int count = 0, none = 0; + std::string name(""), val(""); + + none = saneApi->sane_io_control_api(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; + saneApi->sane_control_option_api(h, 0, SANE_ACTION_GET_VALUE, &dev_options, nullptr); + for(int i = 1; i < dev_options; ++i) + { + const SANE_Option_Descriptor* opt = saneApi->sane_get_option_descriptor_api(h, i); + if(!opt) + continue; + + unsigned int n = i; + if(opt->type == SANE_TYPE_BOOL) + { + SANE_Bool v = SANE_TRUE; + saneApi->sane_io_control_api(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; + saneApi->sane_io_control_api(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; + saneApi->sane_io_control_api(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); + saneApi->sane_io_control_api(h, IO_CTRL_CODE_GET_DEFAULT_VALUE, buf, &n); + std::string langCN(to_default_language(buf, nullptr)); + schm->set_default_value(i, opt->name, &langCN[0], langCN.length()); + 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(); + saneApi->sane_io_control_api(h, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &val[0], &l); + } + } + } + else { + const SANE_Option_Descriptor* opt = reinterpret_cast(saneApi->sane_get_option_descriptor_api(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()); + std::string langCN(from_default_language(buf, nullptr)); + saneApi->sane_control_option_api(h, id, SANE_ACTION_SET_VALUE, &langCN[0], &none); + delete[] buf; + } + else { + saneApi->sane_control_option_api(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& 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(SANEAPI* saneAPI, SANE_Handle handle, const char* scanner_name, const char* scheme = nullptr) + { + handle_ = handle; + opened_scanner_ = scanner_name; + apply_scheme(saneAPI, scheme); + return SANE_STATUS_GOOD; + } + int close_scanner(void) + { + 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& que) + { + for(auto& v: que_) + que.push_back(v.name); + } + int apply_scheme(SANEAPI* saneApi, 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(saneApi, 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_ = v.cfg->get_current_scheme_name(); + v.cfg->save(); + break; + } + } + + return SCANNER_ERR_OK; + } +}; + + +class device_menu : public QMenu +{ + Q_OBJECT + typedef struct _pop_menu + { + QMenu* menu; + std::vector actions; + + bool operator==(const QString& menu_title) + { + return menu->title() == menu_title; + } + }POPMENU; + std::vector menus_; + QAction* cur_action_; + QAction* none_action_; + QActionGroup* group_action_; + std::mutex mutex_; + + QMenu* find_device_menu(const QString& dev_name); + QAction* find_device_config(const QString& dev_name, const QString& cfg_name); + +public: + device_menu(QWidget* parent = nullptr); + device_menu(const QString& title, QWidget* parent = nullptr); + + void deviceMenuUpdate(dev_que* que); + + void connectedDevice(const QString& device); + + void disconnectedDevice(const QString& device); + + void setOptionChecked(const QString& device, const QString& opt, bool checked); + + void get_online_devices(QList& dev_names); + +signals: + void scanOptionsChanged(const QString& device, const QString& opt, bool checked_now); + +private slots: + void on_act_triggered(QAction* act); +}; + +#endif // DEVICE_MENU_H diff --git a/modules/saneui/dialog_device_scan.cpp b/modules/saneui/dialog_device_scan.cpp index 3d754ae3..c556352b 100644 --- a/modules/saneui/dialog_device_scan.cpp +++ b/modules/saneui/dialog_device_scan.cpp @@ -1,6 +1,8 @@ #include "dialog_device_scan.hpp" #include "ui_dialog_device_scan.h" #include "base/HGInc.h" +#include +#include Dialog_Device_Scan::Dialog_Device_Scan(SANEAPI* saneApi, SANE_Handle dev, show_scan_ui_image_callback callback, void *callbackParam, QWidget *parent) : @@ -98,6 +100,16 @@ void Dialog_Device_Scan::on_pushButton_Continue_clicked() ui->label->setText(tr("正在扫描......")); } +void Dialog_Device_Scan::closeEvent(QCloseEvent *e) +{ + if (NULL != m_thread) + { + QMessageBox::warning(this, tr("Warning"), tr("Device is Running")); + e->ignore(); + return; + } +} + void HGAPI Dialog_Device_Scan::ThreadFunc(HGThread thread, HGPointer param) { Dialog_Device_Scan* p = (Dialog_Device_Scan*)param; diff --git a/modules/saneui/dialog_device_scan.hpp b/modules/saneui/dialog_device_scan.hpp index d42dc394..9958f5ca 100644 --- a/modules/saneui/dialog_device_scan.hpp +++ b/modules/saneui/dialog_device_scan.hpp @@ -31,6 +31,9 @@ private slots: void on_pushButton_Complete_clicked(); void on_pushButton_Continue_clicked(); +protected: + virtual void closeEvent(QCloseEvent *e) override; + private: static void HGAPI ThreadFunc(HGThread thread, HGPointer param); diff --git a/modules/saneui/dialog_input.cpp b/modules/saneui/dialog_input.cpp new file mode 100644 index 00000000..1692c79d --- /dev/null +++ b/modules/saneui/dialog_input.cpp @@ -0,0 +1,65 @@ +#include "dialog_input.h" +#include "ui_dialog_input.h" +#include +#include + +Dialog_Input::Dialog_Input(QWidget *parent) : + QDialog(parent), + ui(new Ui::Dialog_Input) +{ + ui->setupUi(this); +} + +Dialog_Input::~Dialog_Input() +{ + delete ui; +} + +void Dialog_Input::on_pushButton_clicked() +{ + QString text = ui->lineEdit->text(); + static QRegularExpression re("\\s"); + text.remove(re);//Remove space + + std::string str(text.toStdString()); + int pos = 0; + while(pos < str.length() && str[pos++] == ' '); + if(--pos > 0) + str.erase(0, pos); + pos = str.length() - 1; + while(pos >= 0) + { + if(str[pos] != ' ') + break; + } + str.erase(pos + 1); + + if(str.empty()) + { + QString title(QString::fromStdString("\351\224\231\350\257\257")), + text(QString::fromStdString("\350\276\223\345\205\245\351\235\236\346\263\225")); + + QMessageBox::warning(this, title, text); + + return; + } + + val_ = QString::fromStdString(str); + done(1); +} + +void Dialog_Input::on_pushButton_2_clicked() +{ + done(0); +} + +void Dialog_Input::init_value(const QString& str) +{ + val_ = str; + ui->lineEdit->setText(str); + ui->lineEdit->setSelection(0, str.length()); +} +QString Dialog_Input::get_inputting_value(void) +{ + return val_; +} diff --git a/modules/saneui/dialog_input.h b/modules/saneui/dialog_input.h new file mode 100644 index 00000000..df8a9fd0 --- /dev/null +++ b/modules/saneui/dialog_input.h @@ -0,0 +1,33 @@ +#ifndef DIALOG_INPUT_H +#define DIALOG_INPUT_H + +#include + +namespace Ui { +class Dialog_Input; +} + +class Dialog_Input : public QDialog +{ + Q_OBJECT + + QString val_; + +public: + explicit Dialog_Input(QWidget *parent = nullptr); + ~Dialog_Input(); + +public: + void init_value(const QString& str); + QString get_inputting_value(void); + +private slots: + void on_pushButton_clicked(); + + void on_pushButton_2_clicked(); + +private: + Ui::Dialog_Input *ui; +}; + +#endif // DIALOG_INPUT_H diff --git a/modules/saneui/dialog_input.ui b/modules/saneui/dialog_input.ui new file mode 100644 index 00000000..1508f61c --- /dev/null +++ b/modules/saneui/dialog_input.ui @@ -0,0 +1,85 @@ + + + Dialog_Input + + + + 0 + 0 + 282 + 82 + + + + Dialog + + + + + + + + -1 + + + 输入: + + + 0 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Ok + + + + + + + Cancel + + + + + + + + + + diff --git a/modules/saneui/gaosixy.cpp b/modules/saneui/gaosixy.cpp new file mode 100644 index 00000000..15de754a --- /dev/null +++ b/modules/saneui/gaosixy.cpp @@ -0,0 +1,54 @@ +#include "gaosixy.h" +#include +#include +#include + +GaoSiXY::GaoSiXY() +{ +} + +void GaoSiXY::solve(double**a,int n,double *recv) +{ + int m = 0; + int i,j; + + for(j = 0; j < n; j++){ + double max = 0; + double imax = 0; + for(i = j; i < n; i++){ + if(imax < fabs(a[i][j])){ + imax = fabs(a[i][j]); + max = a[i][j];//得到各行中所在列最大元素 + m = i; + } + } + if(fabs(a[j][j]) != max) { + double b = 0; + for(int k = j;k < n + 1; k++){ + b = a[j][k]; + a[j][k] = a[m][k]; + a[m][k] = b; } + } + for(int r = j;r < n + 1;r++){ + a[j][r] = a[j][r] / max;//让该行的所在列除以所在列的第一个元素,目的是让首元素为1 + } + for(i = j + 1;i < n; i++){ + double c = a[i][j]; + if(c == 0) continue; + for(int s = j;s < n + 1;s++){ + //double tempdata = a[i][s]; + a[i][s] = a[i][s] - a[j][s] * c;//前后行数相减,使下一行或者上一行的首元素为0 + } + } + } + for(i = n - 2; i >= 0; i--){ + for(j = i + 1;j < n; j++){ + a[i][n] = a[i][n] - a[j][n] * a[i][j]; + } + } + + for(int k = 0; k < n; k++){ + recv[k] = a[k][n]; + } + +} diff --git a/modules/saneui/gaosixy.h b/modules/saneui/gaosixy.h new file mode 100644 index 00000000..4b446756 --- /dev/null +++ b/modules/saneui/gaosixy.h @@ -0,0 +1,17 @@ +#ifndef GAOSIXY_H +#define GAOSIXY_H + +#include +#include + +class GaoSiXY +{ +public: + GaoSiXY(); + void solve(double **a,int n,double *recv);//用于计算曲线方程 + +private: + +}; + +#endif // GAOSIXY_H diff --git a/modules/saneui/hg_settingdialog.cpp b/modules/saneui/hg_settingdialog.cpp new file mode 100644 index 00000000..bd64e7c3 --- /dev/null +++ b/modules/saneui/hg_settingdialog.cpp @@ -0,0 +1,1978 @@ +#include "hg_settingdialog.h" + +#include +#include +#include "cutpapertool.h" +#include "setpicclrtool.h" +#include "base/HGDef.h" +#include "base/HGUtility.h" +#include "HGString.h" +#include "sane/sane_option_definitions.h" +#include "lang/app_language.h" +#include "dialog_input.h" +#include +#include "device_menu.h" + +std::string hg_settingdialog::property_combox_data_type_ = "combox_value_type"; + +hg_settingdialog::hg_settingdialog(SANEAPI* saneApi, SANE_Handle handle, const char *scanner_name, QWidget *parent) + : QDialog(parent) + , save_(false) + , btn_cut_area_(nullptr), btn_gamma_(nullptr), clicked_gamma_(false) + , custom_area_lable_(nullptr), comb_(nullptr) +{ + HGChar cfgpath[512] = {0}; + QString old; + HGBase_GetConfigPath(cfgpath, _countof(cfgpath) - 1); + HGBase_CreateDir(cfgpath); + 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()); + + dev_que_.add_scanner(scanner_name); + dev_que_.open_scanner(saneApi, handle, scanner_name); + + std::string n(dev_que_.opened_scanner_name()); + for(int i = 0; i < dev_que_.scanners(); ++i) + { + SCANNER s = dev_que_.get_at(i); + if(s.name == n) + { + cur_cfg_ = s.cfg; + break; + } + } + cur_scheme_ = cur_cfg_->get_scheme(); + if(!cur_scheme_) + cur_scheme_ = new gb::sane_config_schm(); + cur_scheme_->begin_setting(); + + m_dpiId = -1; + m_dpiValue = 200; + m_paperSizeId = -1; + m_paperSizeValue.clear(); + m_cutLeftId = -1; + m_cutTopId = -1; + m_cutRightId = -1; + m_cutBottomId = -1; + m_cutWidth = 210; + m_cutHeight = 297; + m_cutLeftValue = 0; + m_cutTopValue = 0; + m_cutRightValue = 210; + m_cutBottomValue = 297; + + 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; + + memcpy(&m_saneAPI, saneApi, sizeof(SANEAPI)); + m_devHandle = handle; + initUi(); + on_current_scheme_changed(); + getAppVersion(); +} + +hg_settingdialog::~hg_settingdialog() +{ + cur_scheme_->release(); + cur_cfg_->release(); +} + +void hg_settingdialog::initUi() +{ + updateOpt(); + createUI(); + +#if defined(OEM_ZHONGJING) + setWindowTitle("Microtek DocWizard EX TWAIN"); +#else + setWindowTitle(QString::fromStdString(dev_que_.opened_scanner_name())); +#endif + + setWindowFlags(Qt::Dialog | Qt::WindowCloseButtonHint); + resize(740, height()); +} + +void hg_settingdialog::updateOpt() +{ + bool first = true; + + m_list_defaultOptions.clear(); + + SANE_Int dev_options = 0; + m_saneAPI.sane_control_option_api(m_devHandle, 0, SANE_ACTION_GET_VALUE, &dev_options, nullptr); + for (int i = 1, j= dev_options; i < j; i++) + { + const SANE_Option_Descriptor* opt = m_saneAPI.sane_get_option_descriptor_api(m_devHandle, i); + SANE_Int method = 0; + if (opt == nullptr) + { + m_list_defaultOptions.append(QPair(opt, QVariant(0))); + } + else + { + if(opt->type == SANE_TYPE_INT) + { + SANE_Int init = 0; + + m_saneAPI.sane_control_option_api(m_devHandle, i, SANE_ACTION_GET_VALUE, &init, &method); + m_list_defaultOptions.append(QPair(opt, QVariant(init))); + + if(first) + { + unsigned int n = i; + m_saneAPI.sane_io_control_api(m_devHandle, IO_CTRL_CODE_GET_DEFAULT_VALUE, &init, &n); + cur_scheme_->set_default_value(i, opt->name, (char*)&init, sizeof(init)); + } + } + else if(opt->type == SANE_TYPE_FIXED) + { + SANE_Fixed init = 0; + + m_saneAPI.sane_control_option_api(m_devHandle, i, SANE_ACTION_GET_VALUE, &init, &method); + m_list_defaultOptions.append(QPair(opt, QVariant(init))); + + if(first) + { + unsigned int n = i; + m_saneAPI.sane_io_control_api(m_devHandle, IO_CTRL_CODE_GET_DEFAULT_VALUE, &init, &n); + cur_scheme_->set_default_value(i, opt->name, (char*)&init, sizeof(init)); + } + } + else if(opt->type == SANE_TYPE_BOOL) + { + SANE_Bool init = 0; + + m_saneAPI.sane_control_option_api(m_devHandle, i, SANE_ACTION_GET_VALUE, &init, &method); + m_list_defaultOptions.append(QPair(opt, QVariant(init))); + + if(first) + { + unsigned int n = i; + m_saneAPI.sane_io_control_api(m_devHandle, IO_CTRL_CODE_GET_DEFAULT_VALUE, &init, &n); + cur_scheme_->set_default_value(i, opt->name, (char*)&init, sizeof(init)); + } + } + else if(opt->type == SANE_TYPE_STRING) + { + char *init = (char*)malloc(opt->size * 2 + 4); + + m_saneAPI.sane_control_option_api(m_devHandle, i, SANE_ACTION_GET_VALUE, init, &method); + m_list_defaultOptions.append(QPair(opt, QVariant(QString::fromStdString(init)))); + + if(first) + { + unsigned int n = i; + int err = m_saneAPI.sane_io_control_api(m_devHandle, IO_CTRL_CODE_GET_DEFAULT_VALUE, init, &n); + (void)err; + std::string langCN(to_default_language(init, nullptr)); + cur_scheme_->set_default_value(i, opt->name, &langCN[0], langCN.length()); + } + free(init); + } + else + { + m_list_defaultOptions.append(QPair(opt, QVariant(0))); + } + } + } +} + +QString hg_settingdialog::find_current_scheme_menu(int *scheme_id) +{ + QString text(comb_->currentText()); + + if(scheme_id) + { + if(comb_->currentIndex() >= 0 && comb_->currentIndex() < comb_->count()) + *scheme_id = comb_->currentIndex(); + else { + *scheme_id = -1; + } + } + + return text; +} +void hg_settingdialog::create_scheme_management_ui(QVBoxLayout* layout) +{ + QLabel *title = new QLabel(this); + bool enabled = false; + QHBoxLayout *hbox = new QHBoxLayout(); + int width = 180; + std::vector schemes; + std::string cur_schm(cur_cfg_->get_current_scheme_name()); + + cur_cfg_->get_all_schemes(schemes); + comb_ = new QComboBox(this); + layout->addSpacing(30); + for(int i = 1; i < (int)schemes.size(); ++i) + { + comb_->addItem(QString::fromStdString(schemes[i])); + if(cur_schm == schemes[i]) + { + enabled = true; + comb_->setCurrentText(QString::fromStdString(schemes[i])); + } + } + + if(!enabled) + comb_->setCurrentIndex(-1); + + title->setFixedWidth(width); + comb_->setFixedWidth(width); + + title->setText(tr("existing configuration scheme")); + layout->addWidget(title); + layout->addWidget(comb_); + + rename_ = new QPushButton(this); + rename_->setText(tr("change name")); + rename_->setEnabled(enabled); + rename_->setFixedWidth(width/3); + hbox->addWidget(rename_); + connect(rename_, SIGNAL(clicked(bool)), this, SLOT(slot_pushButton_scheme_management())); + + del_this_ = new QPushButton(this); + del_this_->setText(tr("delete")); + del_this_->setEnabled(enabled); + del_this_->setFixedWidth(width / 3); + hbox->addWidget(del_this_); + connect(del_this_, SIGNAL(clicked(bool)), this, SLOT(slot_pushButton_scheme_management())); + + apply_ = new QPushButton(this); + apply_->setText(tr("apply")); + apply_->setEnabled(enabled); + apply_->setFixedWidth(width / 3); + hbox->addWidget(apply_); + connect(apply_, SIGNAL(clicked(bool)), this, SLOT(slot_pushButton_scheme_management())); + hbox->setSizeConstraint(QLayout::SetFixedSize); + + layout->addLayout(hbox); + layout->addSpacing(10); + + del_all_ = new QPushButton(this); + del_all_->setText(tr("delete all configurations")); + del_all_->setEnabled(enabled); + del_all_->setFixedWidth(width); + layout->addWidget(del_all_); + connect(del_all_, SIGNAL(clicked(bool)), this, SLOT(slot_pushButton_scheme_management())); + + layout->addStretch(); + + title = new QLabel(this); + title->setText(tr("confgiuration information:")); + layout->addWidget(title); + + sketch_ = new QTextEdit(this); + sketch_->setReadOnly(true); + sketch_->setFixedSize(width, 200); + layout->addWidget(sketch_); + + connect(comb_, SIGNAL(currentTextChanged(const QString)), this, SLOT(on_current_scheme_changed())); + on_current_scheme_changed(); +} +void hg_settingdialog::createUI() +{ + QTabWidget *tabWidgetCreation = new QTabWidget(this); + + QPushButton *buttonOk = new QPushButton(this); + buttonOk->setText(tr("ok")); + QPushButton *buttonCancel = new QPushButton(this); + buttonCancel->setText(tr("cancel")); + QHBoxLayout *hlayoutOkAndCancel = new QHBoxLayout; + hlayoutOkAndCancel->addStretch(); + hlayoutOkAndCancel->addWidget(buttonOk); + hlayoutOkAndCancel->addWidget(buttonCancel); + QWidget *widgetOkAndCancel = new QWidget(); + widgetOkAndCancel->setLayout(hlayoutOkAndCancel); + connect(buttonOk, SIGNAL(clicked(bool)), this, SLOT(slot_buttonOkClicked())); + connect(buttonCancel, SIGNAL(clicked(bool)), this, SLOT(slot_buttonCancelClicked())); + + + QHBoxLayout *h = new QHBoxLayout(); + QVBoxLayout *v1 = new QVBoxLayout(), + *v2 = new QVBoxLayout(); + create_scheme_management_ui(v1); + v2->addWidget(tabWidgetCreation); + + QGroupBox *grp = new QGroupBox(tr("configuration scheme management"), this); + grp->setLayout(v1); + grp->setFixedSize(195, 500); + + h->addWidget(grp); + h->addLayout(v2); + + QVBoxLayout* mainVerticalLayout = new QVBoxLayout(this); + mainVerticalLayout->addLayout(h); +// mainVerticalLayout->addWidget(tabWidgetCreation); + mainVerticalLayout->addWidget(widgetOkAndCancel); + this->setLayout(mainVerticalLayout); + + QScrollArea* scrollArea = new QScrollArea; + scrollArea->setWidgetResizable(true); + scrollArea->setAlignment(Qt::AlignCenter); + QFormLayout* layout = new QFormLayout; + + QWidget* widget = new QWidget; + widget->setLayout(layout); + + bool isBegin = true; + std::string cur_val(""); + for (int i = 0; i < m_list_defaultOptions.size(); i++) + { + const SANE_Option_Descriptor* opt = reinterpret_cast(m_list_defaultOptions.at(i).first); + int ind = -1; + + if(opt == nullptr) continue; + h = nullptr; + cur_scheme_->get_config(opt->name, cur_val); + switch (opt->type) + { + case SANE_TYPE_BOOL: + { + QCheckBox *checkBoxCreation = new QCheckBox; + + if (strcmp(opt->name, SANE_STD_OPT_NAME_CUSTOM_AREA) == 0) + { + QWidget* widget_cbtn_pbtn = new QWidget; + widget_cbtn_pbtn->setMaximumWidth(200); + + QLabel *label = new QLabel; + label->setText(QString::fromStdString(opt->title) + QString(" : ")); + + btn_cut_area_ = new QPushButton; + btn_cut_area_->setText(tr("regional crop")); + btn_cut_area_->setFixedWidth(150); + + QHBoxLayout *hLayout = new QHBoxLayout; + hLayout->addWidget(checkBoxCreation); + hLayout->addWidget(btn_cut_area_); + widget_cbtn_pbtn->setLayout(hLayout); + + custom_area_lable_ = label; + + reinterpret_cast(widget->layout())->addRow(label, widget_cbtn_pbtn); + + connect(btn_cut_area_, SIGNAL(clicked(bool)), this, SLOT(slot_cutButtonClicked())); + } + else if (strcmp(opt->name, SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA) == 0) + { + QWidget* widget_cbtn_pbtn = new QWidget(scrollArea); + widget_cbtn_pbtn->setMaximumWidth(200); + btn_gamma_ = new QPushButton(widget_cbtn_pbtn); + btn_gamma_->setText(tr("custom tone curve")); + btn_gamma_->setFixedWidth(150); + + QHBoxLayout *hLayout = new QHBoxLayout; + hLayout->addWidget(checkBoxCreation); + hLayout->addWidget(btn_gamma_); + widget_cbtn_pbtn->setLayout(hLayout); + + reinterpret_cast(widget->layout())->addRow(opt->title + QString(" : "), widget_cbtn_pbtn); + connect(btn_gamma_, SIGNAL(clicked(bool)), this, SLOT(slot_gammaButtonClicked())); + } + else + reinterpret_cast(widget->layout())->addRow(opt->title + QString(" : "), checkBoxCreation); + + checkBoxCreation->setToolTip(opt->desc); + int id = i + 1; + bool enable = *(bool*)&cur_val[0]; + checkBoxCreation->setProperty("controls_id", id); + checkBoxCreation->setChecked(enable); + if (strcmp(opt->name, SANE_STD_OPT_NAME_CUSTOM_AREA) == 0) + btn_cut_area_->setEnabled(enable); + else if (strcmp(opt->name, SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA) == 0) + btn_gamma_->setEnabled(enable); + connect(checkBoxCreation, SIGNAL(stateChanged(int)), this, SLOT(slot_checkedClicked())); + m_list_widgets.append(checkBoxCreation); + + m_list_getOpt.append(QPair(id, opt)); + break; + } + + case SANE_TYPE_INT: + { + switch(opt->constraint_type) + { + case SANE_CONSTRAINT_NONE: + { + QSpinBox* spinBox = new QSpinBox(scrollArea); + spinBox->setMinimumWidth(150); + spinBox->setToolTip(opt->desc); + spinBox->setRange(1, 1000); + int id = i + 1; + spinBox->setProperty("controls_id", id); + + QHBoxLayout* hLayout = new QHBoxLayout; + hLayout->addWidget(spinBox); + hLayout->addStretch(); + reinterpret_cast(widget->layout())->addRow(opt->title + QString(" : "), spinBox); + + m_list_widgets.append(spinBox); + m_list_getOpt.append(QPair(id, opt)); + + spinBox->setValue(*(int*)&cur_val[0]); + connect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(slot_spinBoxClicked(int))); + break; + } + + case SANE_CONSTRAINT_RANGE: + { + QWidget* widget_slider_spin = new QWidget(scrollArea); + widget_slider_spin->setMinimumWidth(300); + + QSlider* sliderCreation = new QSlider(widget_slider_spin); + sliderCreation->setOrientation(Qt::Horizontal); + sliderCreation->setMinimumWidth(120); + sliderCreation->setRange(opt->constraint.range->min, opt->constraint.range->max); + sliderCreation->setToolTip(opt->desc); + sliderCreation->setProperty("controls_id", i+1); + sliderCreation->setValue(m_list_defaultOptions.at(i).second.toInt()); + + QSpinBox* spinBox = new QSpinBox(widget_slider_spin); + spinBox->setMinimumWidth(150); + spinBox->setToolTip(opt->desc); + spinBox->setRange(opt->constraint.range->min, opt->constraint.range->max); + + spinBox->setSingleStep(1); + spinBox->setValue(m_list_defaultOptions.at(i).second.toInt()); + int id = i + 1; + spinBox->setProperty("controls_id", id); + m_list_sliderSpinbox.append(QPair(sliderCreation, spinBox)); + + QHBoxLayout* hLayout = new QHBoxLayout; + hLayout->addWidget(sliderCreation); + hLayout->addWidget(spinBox); +// hLayout->addStretch(); + widget_slider_spin->setLayout(hLayout); + reinterpret_cast(widget->layout())->addRow(opt->title + QString(" : "), widget_slider_spin); + + m_list_widgets.append(sliderCreation); + m_list_widgets.append(spinBox); + m_list_getOpt.append(QPair(id, opt)); + + int cur = *(int*)&cur_val[0]; + spinBox->setValue(cur); + sliderCreation->setValue(cur); + + connect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(slot_spinBoxClicked(int))); + connect(sliderCreation, SIGNAL(valueChanged(int)), this, SLOT(slot_sliderClicked(int))); + + break; + } + + case SANE_CONSTRAINT_WORD_LIST: + { + QComboBox* comboBoxCreation = new QComboBox(scrollArea); + comboBoxCreation->setToolTip(opt->desc); + int id = i + 1; + comboBoxCreation->setProperty("controls_id", id); + reinterpret_cast(widget->layout())->addRow(opt->title + QString(" : "), comboBoxCreation); + + auto p_str = opt->constraint.word_list; + char buf[20]; + for(SANE_Int i = 0; i < p_str[0]; ++i) + { + sprintf(buf, "%d", p_str[i + 1]); + comboBoxCreation->addItem(QString::fromStdString(buf)); + } + sprintf(buf, "%d", m_list_defaultOptions.at(i).second.toInt()); + comboBoxCreation->setProperty(hg_settingdialog::property_combox_data_type_.c_str(), COMBO_VAL_INT); + m_list_widgets.append(comboBoxCreation); + m_list_getOpt.append(QPair(id, opt)); + + char nstr[40] = {0}; + sprintf(nstr, "%d", *(int*)&cur_val[0]); + comboBoxCreation->setCurrentText(QString::fromStdString(nstr)); + connect(comboBoxCreation, SIGNAL(currentTextChanged(const QString)), this, SLOT(slot_string_list_comboBoxClicked())); + break; + } + + case SANE_CONSTRAINT_STRING_LIST: + break; + } + break; + } + + case SANE_TYPE_FIXED: + { + QWidget* widget_slider_spin = new QWidget(scrollArea); + widget_slider_spin->setMinimumWidth(300); + QSlider* sliderCreation = new QSlider(widget_slider_spin); + sliderCreation->setOrientation(Qt::Horizontal); + sliderCreation->setMinimumWidth(120); + sliderCreation->setToolTip(opt->desc); + int id = i + 1; + sliderCreation->setProperty("controls_id", id); + sliderCreation->setRange(SANE_UNFIX(opt->constraint.range->min) * 100, SANE_UNFIX(opt->constraint.range->max) * 100); + sliderCreation->setValue(SANE_UNFIX(m_list_defaultOptions.at(i).second.toDouble()) * 100); + + QDoubleSpinBox* spinBox = new QDoubleSpinBox(widget_slider_spin); + spinBox->setMinimumWidth(150); + spinBox->setToolTip(opt->desc); + spinBox->setDecimals(2); + spinBox->setSingleStep(0.01); + spinBox->setRange(SANE_UNFIX(opt->constraint.range->min), SANE_UNFIX(opt->constraint.range->max)); + spinBox->setValue(sliderCreation->value() * spinBox->singleStep()); + spinBox->setProperty("controls_id", id); + + m_list_sliderSpinbox.append(QPair(sliderCreation, spinBox)); + + QHBoxLayout* hLayout = new QHBoxLayout; + hLayout->addWidget(sliderCreation); + hLayout->addWidget(spinBox); +// hLayout->addStretch(); + widget_slider_spin->setLayout(hLayout); + reinterpret_cast(widget->layout())->addRow(opt->title + QString(" : "), widget_slider_spin); + + m_list_widgets.append(sliderCreation); + m_list_widgets.append(spinBox); + + m_list_getOpt.append(QPair(id, opt)); +// iniRead(md5(opt->title), id, sliderCreation); +// iniRead(md5(opt->title), id, spinBox); + + float v = SANE_UNFIX(*(SANE_Fixed*)&cur_val[0]); + sliderCreation->setValue(v * 100); + spinBox->setValue(sliderCreation->value() * spinBox->singleStep()); + connect(spinBox, SIGNAL(valueChanged(double)), this, SLOT(slot_doubleSpinboxClicked(double))); + connect(sliderCreation, SIGNAL(valueChanged(int)), this, SLOT(slot_sliderClicked(int))); + break; + } + + case SANE_TYPE_STRING: + { + switch(opt->constraint_type) + { + case SANE_CONSTRAINT_NONE: + { + QLineEdit *lineEdit = new QLineEdit(scrollArea); + lineEdit->setToolTip(opt->desc); + int id = i + 1; + lineEdit->setProperty("controls_id", id); + reinterpret_cast(widget->layout())->addRow(opt->title + QString(" : "), lineEdit); + + m_list_widgets.append(lineEdit); + m_list_getOpt.append(QPair(id, opt)); +// iniRead(md5(opt->title), id, lineEdit); + + lineEdit->setText(QString::fromStdString(cur_val)); + connect(lineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(slot_lineEditInput())); + break; + } + + case SANE_CONSTRAINT_RANGE: + break; + case SANE_CONSTRAINT_WORD_LIST: + break; + + case SANE_CONSTRAINT_STRING_LIST: + { + QComboBox* comboBoxCreation = new QComboBox(scrollArea); + comboBoxCreation->setToolTip(opt->desc); + int id = i + 1; + comboBoxCreation->setProperty("controls_id", id); + reinterpret_cast(widget->layout())->addRow(opt->title + QString(" : "), comboBoxCreation); + + auto p_str = opt->constraint.string_list; + QStringList stringList; + while(*p_str) + { + stringList.append(*p_str); + p_str++; + } + + if(stringList.isEmpty() != true) + { + for(int i = 0; i < (stringList.size()); i++) + comboBoxCreation->addItem(stringList.at(i)); + } + comboBoxCreation->setCurrentText(m_list_defaultOptions.at(i).second.toString()); + comboBoxCreation->setProperty(hg_settingdialog::property_combox_data_type_.c_str(), COMBO_VAL_STRING); + //printf("Option %02d default value is: %s\n", i + 1, m_list_defaultOptions.at(i).second.toString().data()); + + m_list_widgets.append(comboBoxCreation); + + m_list_getOpt.append(QPair(id, opt)); +// iniRead(md5(opt->title), id, comboBoxCreation); + + comboBoxCreation->setCurrentText(QString::fromStdString(cur_val)); + connect(comboBoxCreation, SIGNAL(currentTextChanged(const QString)), this, SLOT(slot_string_list_comboBoxClicked())); + break; + } + } + break; + } + + case SANE_TYPE_BUTTON: + { + QPushButton* pushButton = new QPushButton(this); + pushButton->setText(opt->title); + pushButton->setToolTip(opt->desc); + int id = i + 1; + pushButton->setProperty("controls_id", id); + hlayoutOkAndCancel->insertWidget(0, pushButton, 0, Qt::AlignRight); + + connect(pushButton, SIGNAL(clicked(bool)), this, SLOT(slot_pushButtonClicked())); + break; + } + + case SANE_TYPE_GROUP: + { + if (isBegin) + { + scrollArea->setWindowTitle(opt->title); + isBegin = false; + }else{ + scrollArea->setWidget(widget); + tabWidgetCreation->addTab(scrollArea, scrollArea->windowTitle()); + scrollArea = new QScrollArea; + scrollArea->setWidgetResizable(true); + scrollArea->setWindowTitle(opt->title); + layout = new QFormLayout; + widget = new QWidget; + widget->setLayout(layout); + } + + m_list_widgets.append(nullptr); + break; + } + } //switch(opt->type) + +// if (Utf8ToStdString(opt->title) == "分辨率") + if (strcmp(opt->name, SANE_STD_OPT_NAME_RESOLUTION) == 0) + { + m_dpiId = i + 1; + m_dpiValue = m_list_defaultOptions.at(i).second.toInt(); + } +// else if (Utf8ToStdString(opt->title) == "纸张尺寸") + else if (strcmp(opt->name, SANE_STD_OPT_NAME_PAPER) == 0) + { + m_paperSizeId = i + 1; + m_paperSizeValue = m_list_defaultOptions.at(i).second.toString(); + } + + if (0 == strcmp(opt->name, SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT)) + { + m_cutLeftId = i + 1; + m_cutLeftValue = SANE_UNFIX(m_list_defaultOptions.at(i).second.toInt()); + if (opt->constraint_type == SANE_CONSTRAINT_RANGE) + m_cutWidth = SANE_UNFIX(opt->constraint.range->max); + } + else if (0 == strcmp(opt->name, SANE_STD_OPT_NAME_CUSTOM_AREA_TOP)) + { + m_cutTopId = i + 1; + m_cutTopValue = SANE_UNFIX(m_list_defaultOptions.at(i).second.toInt()); + if (opt->constraint_type == SANE_CONSTRAINT_RANGE) + m_cutHeight = SANE_UNFIX(opt->constraint.range->max); + } + else if (0 == strcmp(opt->name, SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT)) + { + m_cutRightId = i + 1; + m_cutRightValue = SANE_UNFIX(m_list_defaultOptions.at(i).second.toInt()); + } + else if (0 == strcmp(opt->name, SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM)) + { + m_cutBottomId = i + 1; + m_cutBottomValue = SANE_UNFIX(m_list_defaultOptions.at(i).second.toInt()); + } + +// else if (Utf8ToStdString(opt->title) == "颜色模式") + if (strcmp(opt->name, SANE_STD_OPT_NAME_COLOR_MODE) == 0) + { + m_colorModeId = i + 1; + m_colorModeValue = m_list_defaultOptions.at(i).second.toString(); + } +// else if (Utf8ToStdString(opt->title) == "伽玛" || Utf8ToStdString(opt->title) == "伽玛值") + + } //for + + updateUIStatus(); + + scrollArea->setWidget(widget); + tabWidgetCreation->addTab(scrollArea, scrollArea->windowTitle()); +} + +void hg_settingdialog::refresh_control_value(int op_id) +{ + QVector ctrls = find_control(op_id); + + if(ctrls.empty()) + return; + + const SANE_Option_Descriptor* opt = (const SANE_Option_Descriptor*)m_list_defaultOptions.at(op_id - 1).first; + if(opt->type == SANE_TYPE_BOOL) + { + for(size_t i = 0; i < (size_t)ctrls.size(); ++i) + { + QCheckBox* cb = qobject_cast(ctrls[i]); + if(cb) + { + disconnect(cb, SIGNAL(stateChanged(int)), this, SLOT(slot_checkedClicked())); + cb->setChecked(m_list_defaultOptions.at(op_id - 1).second.toBool()); + connect(cb, SIGNAL(stateChanged(int)), this, SLOT(slot_checkedClicked())); + break; + } + } + } + else if(opt->type == SANE_TYPE_INT) + { + for(size_t i = 0; i < (size_t)ctrls.size(); ++i) + { + QComboBox* comb = qobject_cast(ctrls[i]); + if(comb) + { + char buf[40] = {0}; + sprintf(buf, "%d", m_list_defaultOptions.at(op_id - 1).second.toInt()); + comb->disconnect(comb, SIGNAL(currentTextChanged(const QString)), this, SLOT(slot_string_list_comboBoxClicked())); + comb->setCurrentText(QString::fromStdString(buf)); + connect(comb, SIGNAL(currentTextChanged(const QString)), this, SLOT(slot_string_list_comboBoxClicked())); + } + else + { + QSlider* slider = qobject_cast(ctrls[i]); + if(slider) + { + disconnect(slider, SIGNAL(valueChanged(int)), this, SLOT(slot_sliderClicked(int))); + slider->setValue(m_list_defaultOptions.at(op_id - 1).second.toInt()); + connect(slider, SIGNAL(valueChanged(int)), this, SLOT(slot_sliderClicked(int))); + } + else + { + QSpinBox* spin = qobject_cast(ctrls[i]); + if(spin) + { + disconnect(spin, SIGNAL(valueChanged(int)), this, SLOT(slot_spinBoxClicked(int))); + spin->setValue(m_list_defaultOptions.at(op_id - 1).second.toInt()); + connect(spin, SIGNAL(valueChanged(int)), this, SLOT(slot_spinBoxClicked(int))); + } + } + } + } + } + else if(opt->type == SANE_TYPE_FIXED) + { + double val = SANE_UNFIX(m_list_defaultOptions.at(op_id - 1).second.toInt()); + QSlider *slider = NULL; + QDoubleSpinBox* spin = NULL; + for(size_t i = 0; i < (size_t)ctrls.size(); ++i) + { + QComboBox* comb = qobject_cast(ctrls[i]); + if(comb) + { + char buf[40] = {0}; + sprintf(buf, "%f", val); + comb->disconnect(comb, SIGNAL(currentTextChanged(const QString)), this, SLOT(slot_string_list_comboBoxClicked())); + comb->setCurrentText(QString::fromStdString(buf)); + connect(comb, SIGNAL(currentTextChanged(const QString)), this, SLOT(slot_string_list_comboBoxClicked())); + } + else if(!slider) + { + slider = qobject_cast(ctrls[i]); + if(slider) + disconnect(slider, SIGNAL(valueChanged(int)), this, SLOT(slot_sliderClicked(int))); + } + else if(!spin) + { + spin = qobject_cast(ctrls[i]); + if(spin) + disconnect(spin, SIGNAL(valueChanged(double)), this, SLOT(slot_spinBoxClicked(double))); + } + } + if(slider) + slider->setValue(val * 100); + if(spin) + spin->setValue(val); + if(slider) + connect(slider, SIGNAL(valueChanged(int)), this, SLOT(slot_sliderClicked(int))); + if(spin) + connect(spin, SIGNAL(valueChanged(double)), this, SLOT(slot_spinBoxClicked(double))); + } + else if(opt->type == SANE_TYPE_STRING) + { + for(size_t i = 0; i < (size_t)ctrls.size(); ++i) + { + QComboBox* comb = qobject_cast(ctrls[i]); + if(comb) + { + disconnect(comb, SIGNAL(currentTextChanged(const QString)), this, SLOT(slot_string_list_comboBoxClicked())); + comb->setCurrentText(m_list_defaultOptions.at(op_id - 1).second.toString()); + // comb->setProperty(hg_settingdialog::property_combox_data_type_.c_str(), COMBO_VAL_STRING); + connect(comb, SIGNAL(currentTextChanged(const QString)), this, SLOT(slot_string_list_comboBoxClicked())); + } + else + { + QLineEdit* edit = qobject_cast(ctrls[i]); + if(edit) + { + disconnect(edit, SIGNAL(textChanged(const QString&)), this, SLOT(slot_lineEditInput())); + edit->setText(m_list_defaultOptions.at(op_id - 1).second.toString()); + connect(edit, SIGNAL(textChanged(const QString&)), this, SLOT(slot_lineEditInput())); + } + } + } + } +} +QVector hg_settingdialog::find_control(int opt_num) +{ + QVector list_w; + for(int i = 0; i< m_list_widgets.size(); i++) + { + if (m_list_widgets.at(i) == nullptr) continue; + QWidget* w = m_list_widgets.at(i); + int id = w->property("controls_id").toInt(); + if(opt_num == id) + list_w.append(w); + } + return list_w; +} + +void hg_settingdialog::updateUIStatus() +{ + updateOpt(); + + SANE_Int dev_options = 0; + m_saneAPI.sane_control_option_api(m_devHandle, 0, SANE_ACTION_GET_VALUE, &dev_options, nullptr); + for(int id = 1, optons = dev_options; id < optons; id++) + { + QVector list_widgets = find_control(id); + if (list_widgets.empty()) continue; + QWidget* widget = list_widgets.first(); + if (widget == nullptr) continue; + QWidget* parentWidget = widget->parentWidget(); + + while (parentWidget->layout() && + typeid(*(parentWidget->layout())) != typeid(QFormLayout)) + { + widget = parentWidget; + parentWidget = widget->parentWidget(); + } + + QFormLayout* layout = reinterpret_cast(parentWidget->layout()); + const SANE_Option_Descriptor* opt = reinterpret_cast(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->name, SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT) == 0 || + strcmp(opt->name, SANE_STD_OPT_NAME_CUSTOM_AREA_TOP) == 0 || + strcmp(opt->name, SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT) == 0 || + strcmp(opt->name, SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM) == 0 ) + hide = true; + + refresh_control_value(id); + if(w_label) + hide ? w_label->hide() : w_label->show(); + widget->setVisible(!hide); + if(strcmp(opt->name, SANE_STD_OPT_NAME_CUSTOM_AREA) == 0) + { + if(hide) + { + custom_area_lable_->hide(); + btn_cut_area_->hide(); + } + else + { + custom_area_lable_->show(); + btn_cut_area_->show(); + } + } + } +} + +void hg_settingdialog::slot_checkedClicked() +{ + QCheckBox *checkBox = qobject_cast(sender()); + SANE_Int id = checkBox->property("controls_id").toInt(); + SANE_Bool checkBoxcurrentState = checkBox->isChecked(); + + const SANE_Option_Descriptor* opt = nullptr; + for(int i = 0; i < m_list_getOpt.size(); i++) + if (m_list_getOpt.at(i).first == id) + { + opt = reinterpret_cast(m_list_getOpt.at(i).second); + break; + } + + m_list_IdValueTitle.append(QPair, QString>(QPair(id, checkBoxcurrentState), md5(opt->title))); + + SANE_Int method = 0; + m_saneAPI.sane_control_option_api(m_devHandle, id, SANE_ACTION_SET_VALUE, &checkBoxcurrentState, &method); + if((method & SANE_INFO_RELOAD_OPTIONS) == SANE_INFO_RELOAD_OPTIONS) + updateUIStatus(); + else if(method & SANE_INFO_INEXACT) + checkBox->setCheckState(checkBoxcurrentState ? Qt::CheckState::Checked : Qt::CheckState::Unchecked); + + if(strcmp(opt->name, SANE_STD_OPT_NAME_CUSTOM_AREA) == 0) + btn_cut_area_->setEnabled(checkBoxcurrentState); + else if (strcmp(opt->name, SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA) == 0) + btn_gamma_->setEnabled(checkBoxcurrentState); + cur_scheme_->config_changed(id, (char*)&checkBoxcurrentState, sizeof(checkBoxcurrentState)); +} + +void hg_settingdialog::slot_string_list_comboBoxClicked() +{ + QComboBox *comboBox = qobject_cast(sender()); + SANE_Int id = comboBox->property("controls_id").toInt(); + std::string comboBoxcurrentItem(comboBox->currentText().toUtf8()); + int type = comboBox->property(hg_settingdialog::property_combox_data_type_.c_str()).toInt(); + + if (id == m_dpiId) + { + m_dpiValue = atoi(comboBoxcurrentItem.c_str()); + qDebug("dpi=%d", m_dpiValue); + } + else if (id == m_paperSizeId) + { + m_paperSizeValue = comboBoxcurrentItem.c_str(); + qDebug("paperSize=%s", comboBoxcurrentItem.c_str()); + } + else if (id == m_colorModeId) + { + m_colorModeValue = comboBoxcurrentItem.c_str(); + qDebug("colorMode=%s", comboBoxcurrentItem.c_str()); + } + + const SANE_Option_Descriptor* opt = nullptr; + for(int i = 0; i < m_list_getOpt.size(); i++) + if (m_list_getOpt.at(i).first == id) + { + opt = reinterpret_cast(m_list_getOpt.at(i).second); + break; + } + + m_list_IdValueTitle.append(QPair, QString>(QPair(id, &comboBoxcurrentItem.at(0)), md5(opt->title))); + + SANE_Int method = 0; + SANE_String buf = (SANE_String)malloc(opt->size * 2 + 4); + if(type == COMBO_VAL_INT) + *((SANE_Int*)buf) = atoi(comboBoxcurrentItem.c_str()); + else if(type == COMBO_VAL_FLOAT) + *((SANE_Fixed*)buf) = SANE_FIX(atof(comboBoxcurrentItem.c_str())); + else + strcpy(buf, comboBoxcurrentItem.c_str()); + m_saneAPI.sane_control_option_api(m_devHandle, id, SANE_ACTION_SET_VALUE, buf, &method); + if((method & SANE_INFO_RELOAD_OPTIONS) == SANE_INFO_RELOAD_OPTIONS) + updateUIStatus(); + else if(method & SANE_INFO_INEXACT) + comboBox->setCurrentText(QString::fromStdString(buf)); + + if(type == COMBO_VAL_INT) + cur_scheme_->config_changed(id, buf, sizeof(SANE_Int)); + else if(type == COMBO_VAL_FLOAT) + cur_scheme_->config_changed(id, buf, sizeof(SANE_Fixed)); + else + { + std::string langCN(to_default_language(buf, nullptr)); + cur_scheme_->config_changed(id, &langCN[0], langCN.length()); + } + free(buf); +} + +void hg_settingdialog::slot_pushButtonClicked() +{ + QPushButton *pushButton = qobject_cast(sender()); + SANE_Int id = pushButton->property("controls_id").toInt(), + after = 0; + + // restore to default setting ? + m_saneAPI.sane_control_option_api(m_devHandle, id, SANE_ACTION_SET_VALUE, NULL, &after); + if((after & SANE_INFO_RELOAD_OPTIONS) == SANE_INFO_RELOAD_OPTIONS) + updateUIStatus(); + + const SANE_Option_Descriptor* opt = m_saneAPI.sane_get_option_descriptor_api(m_devHandle, id); + if(opt && strcmp(opt->name, SANE_STD_OPT_NAME_RESTORE) == 0) + { + restore_2_default_settings(); + } +} + +void hg_settingdialog::slot_cutButtonClicked() +{ + //int width = 0.03937 * m_cutWidth * m_dpiValue; + //int height = 0.03937 * m_cutHeight * m_dpiValue; + int left = 0.03937 * m_cutLeftValue * m_dpiValue; + int top = 0.03937 * m_cutTopValue * m_dpiValue; + int right = 0.03937 * m_cutRightValue * m_dpiValue; + int bottom = 0.03937 * m_cutBottomValue * m_dpiValue; + + CutPaperTool dlg(this); + dlg.setPaperType(m_dpiValue, m_paperSizeValue, 300); + QRectF rc(left, top, right - left, bottom - top); + dlg.setCutRect(rc); + if (dlg.exec()) + { + QRectF rcRet = dlg.getCutRectPixel(); + + m_cutLeftValue = rcRet.left() / (0.03937 * m_dpiValue); + m_cutTopValue = rcRet.top() / (0.03937 * m_dpiValue); + m_cutRightValue = rcRet.right() / (0.03937 * m_dpiValue); + m_cutBottomValue = rcRet.bottom() / (0.03937 * m_dpiValue); + + SANE_Int info; + SANE_Word value = SANE_FIX(m_cutLeftValue); + m_saneAPI.sane_control_option_api(m_devHandle, m_cutLeftId, SANE_ACTION_SET_VALUE, &value, &info); + cur_scheme_->config_changed(m_cutLeftId, (char*)&value, sizeof(value)); + value = SANE_FIX(m_cutTopValue); + m_saneAPI.sane_control_option_api(m_devHandle, m_cutTopId, SANE_ACTION_SET_VALUE, &value, &info); + cur_scheme_->config_changed(m_cutTopId, (char*)&value, sizeof(value)); + value = SANE_FIX(m_cutRightValue); + m_saneAPI.sane_control_option_api(m_devHandle, m_cutRightId, SANE_ACTION_SET_VALUE, &value, &info); + cur_scheme_->config_changed(m_cutRightId, (char*)&value, sizeof(value)); + value = SANE_FIX(m_cutBottomValue); + m_saneAPI.sane_control_option_api(m_devHandle, m_cutBottomId, SANE_ACTION_SET_VALUE, &value, &info); + cur_scheme_->config_changed(m_cutBottomId, (char*)&value, sizeof(value)); + } +} + +void hg_settingdialog::slot_gammaButtonClicked() +{ + setPicClrTool dlg(this); + + int colorMode; // 0-彩色, 1-灰度 + if (m_colorModeValue.toStdString() == OPTION_VALUE_YSMS_256JHD + || m_colorModeValue.toStdString() == OPTION_VALUE_YSMS_HB) + { + colorMode = 1; + + QList keyTable; + for (int i = 0; i < m_gammaData.pt_count; ++i) + { + QPoint pt(m_gammaData.keypoint[i].x, m_gammaData.keypoint[i].y); + keyTable.append(pt); + } + + if (!keyTable.empty()) + { + dlg.setGrayKeyTable(keyTable); + } + } + else + { + colorMode = 0; + + QList keyTable; + for (int i = 0; i < m_gammaData.pt_count; ++i) + { + QPoint pt(m_gammaData.keypoint[i].x, m_gammaData.keypoint[i].y); + keyTable.append(pt); + } + + QList rKeyTable; + for (int i = 0; i < m_gammaData.pt_count_r; ++i) + { + QPoint pt(m_gammaData.keypoint_r[i].x, m_gammaData.keypoint_r[i].y); + rKeyTable.append(pt); + } + + QList gKeyTable; + for (int i = 0; i < m_gammaData.pt_count_g; ++i) + { + QPoint pt(m_gammaData.keypoint_g[i].x, m_gammaData.keypoint_g[i].y); + gKeyTable.append(pt); + } + + QList bKeyTable; + for (int i = 0; i < m_gammaData.pt_count_b; ++i) + { + QPoint pt(m_gammaData.keypoint_b[i].x, m_gammaData.keypoint_b[i].y); + bKeyTable.append(pt); + } + + QVector> keyTableList; + if (!keyTable.empty() && !rKeyTable.empty() && !gKeyTable.empty() && !bKeyTable.empty()) + { + keyTableList.append(keyTable); + keyTableList.append(rKeyTable); + keyTableList.append(gKeyTable); + keyTableList.append(bKeyTable); + dlg.setRGBKeyTable(keyTableList); + } + } + + dlg.setColorMode(colorMode); + if (dlg.exec()) + { + memset(&m_gammaData, 0, sizeof(m_gammaData)); + clicked_gamma_ = true; + + if (1 == colorMode) + { + QList keyTable = dlg.getGrayKeyTable(); + + m_gammaData.pt_count = HGMIN(4, keyTable.size()); + int i = 0; + for (QPoint pt : keyTable) + { + if (i >= 4) + break; + + m_gammaData.keypoint[i].x = pt.x(); + m_gammaData.keypoint[i].y = pt.y(); + ++i; + } + + uchar data[256]; + dlg.getGrayTable(data, 256); + for (int i = 0; i < 256; ++i) + { + m_gammaData.table[i] = data[i]; + } + } + else + { + QVector> keyTableList = dlg.getRGBKeyTable(); + + m_gammaData.pt_count = HGMIN(4, keyTableList[0].size()); + int i = 0; + for (QPoint pt : keyTableList[0]) + { + if (i >= 4) + break; + + m_gammaData.keypoint[i].x = pt.x(); + m_gammaData.keypoint[i].y = pt.y(); + ++i; + } + + m_gammaData.pt_count_r = HGMIN(4, keyTableList[1].size()); + i = 0; + for (QPoint pt : keyTableList[1]) + { + if (i >= 4) + break; + + m_gammaData.keypoint_r[i].x = pt.x(); + m_gammaData.keypoint_r[i].y = pt.y(); + ++i; + } + + m_gammaData.pt_count_g = HGMIN(4, keyTableList[2].size()); + i = 0; + for (QPoint pt : keyTableList[2]) + { + if (i >= 4) + break; + + m_gammaData.keypoint_g[i].x = pt.x(); + m_gammaData.keypoint_g[i].y = pt.y(); + ++i; + } + + m_gammaData.pt_count_b = HGMIN(4, keyTableList[3].size()); + i = 0; + for (QPoint pt : keyTableList[3]) + { + if (i >= 4) + break; + + m_gammaData.keypoint_b[i].x = pt.x(); + m_gammaData.keypoint_b[i].y = pt.y(); + ++i; + } + + uchar data[256 * 3]; + dlg.getRGBTable(data, 256 * 3); + for (int i = 0; i < 256; ++i) + { + m_gammaData.table[i] = data[i * 3 + 2]; + m_gammaData.table[i + 256] = data[i * 3 + 1]; + m_gammaData.table[i + 512] = data[i * 3 + 0]; + } + } + + unsigned int len = sizeof(SANE_Gamma); + m_saneAPI.sane_io_control_api(m_devHandle, IO_CTRL_CODE_SET_CUSTOM_GAMMA, &m_gammaData, &len); + cur_scheme_->config_changed(SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA, (char*)&m_gammaData, sizeof(m_gammaData), true); + } +} + +void hg_settingdialog::slot_word_list_comboBoxClicked(int value) +{ + QComboBox *comboBox = qobject_cast(sender()); + SANE_Int id = comboBox->property("controls_id").toInt(); + SANE_Int temp = value; + + const SANE_Option_Descriptor* opt = nullptr; + for(int i = 0; i < m_list_getOpt.size(); i++) + if (m_list_getOpt.at(i).first == id) + { + opt = reinterpret_cast(m_list_getOpt.at(i).second); + break; + } + m_list_IdValueTitle.append(QPair, QString>(QPair(id, temp), md5(opt->title))); + + + SANE_Int method = 0; + m_saneAPI.sane_control_option_api(m_devHandle, id, SANE_ACTION_SET_VALUE, &temp, &method); + if((method & SANE_INFO_RELOAD_OPTIONS) == SANE_INFO_RELOAD_OPTIONS) + updateUIStatus(); + else if(method & SANE_INFO_INEXACT) + { + char buf[20]; + sprintf(buf, "%d", temp); + comboBox->setCurrentText(QString::fromStdString(buf)); + } + cur_scheme_->config_changed(id, (char*)&temp, sizeof(temp)); +} + +void hg_settingdialog::slot_sliderClicked(int value) +{ + QSlider *slider = qobject_cast(sender()); + SANE_Int id = slider->property("controls_id").toInt(); + + const SANE_Option_Descriptor* opt = nullptr; + for(int i = 0; i < m_list_getOpt.size(); i++) + if (m_list_getOpt.at(i).first == id) + { + opt = reinterpret_cast(m_list_getOpt.at(i).second); + break; + } + + QAbstractSpinBox* spin = nullptr; + for(int i = 0; i < m_list_sliderSpinbox.size(); i++) + if (m_list_sliderSpinbox.at(i).first == slider) + { + spin = reinterpret_cast(m_list_sliderSpinbox.at(i).second); + break; + } + + if (spin != nullptr) + { + SANE_Int val = value, method = 0; + bool db_val = false; + if (typeid(*spin) == typeid(QSpinBox)) + { + QSpinBox* spin_ = reinterpret_cast(spin); + spin_->setValue(value); + + m_list_IdValueTitle.append(QPair, QString>(QPair(id, val), md5(opt->title))); + } + else + { + QDoubleSpinBox* spin_ = reinterpret_cast(spin); + double temp = value * spin_->singleStep(); + if(temp != spin_->value()) + spin_->setValue(temp); + + val = SANE_FIX(temp); + db_val = true; + + m_list_IdValueTitle.append(QPair, QString>(QPair(id, temp), md5(opt->title))); + } + m_saneAPI.sane_control_option_api(m_devHandle, id, SANE_ACTION_SET_VALUE, &val, &method); + if((method & SANE_INFO_RELOAD_OPTIONS) == SANE_INFO_RELOAD_OPTIONS) + updateUIStatus(); + else if(method & SANE_INFO_INEXACT) + { + if(db_val) + { + QDoubleSpinBox* spin_ = reinterpret_cast(spin); + double v = SANE_UNFIX(val); + spin_->setValue(v); + slider->setValue(spin_->value() / spin_->singleStep()); + } + else { + QSpinBox* spin_ = reinterpret_cast(spin); + spin_->setValue(val); + slider->setValue(spin_->value() / spin_->singleStep()); + } + } + cur_scheme_->config_changed(id, (char*)&val, sizeof(val)); + } +} + +void hg_settingdialog::slot_doubleSpinboxClicked(double value) +{ + QDoubleSpinBox* spinBox = qobject_cast(sender()); + QAbstractSlider* slider = nullptr; + int id = spinBox->property("controls_id").toInt(); + for (int i = 0; i < m_list_sliderSpinbox.size(); i++) + if (m_list_sliderSpinbox.at(i).second == spinBox) + { + slider = reinterpret_cast(m_list_sliderSpinbox.at(i).first); + break; + } + if(slider != nullptr) + { + int temp = static_cast(value / spinBox->singleStep() + 0.5); + QSlider* slider_ = reinterpret_cast(slider); + if (slider_->value() != temp) + slider_->setValue(temp); + } +} + +void hg_settingdialog::slot_spinBoxClicked(int value) +{ + QSpinBox* spinBox = qobject_cast(sender()); + int id = spinBox->property("controls_id").toInt(); + + const SANE_Option_Descriptor* opt = nullptr; + for(int i = 0; i < m_list_getOpt.size(); i++) + if (m_list_getOpt.at(i).first == id) + { + opt = reinterpret_cast(m_list_getOpt.at(i).second); + break; + } + + QAbstractSlider* slider = nullptr; + for (int i = 0; i < m_list_sliderSpinbox.size(); i++) + if (m_list_sliderSpinbox.at(i).second == spinBox) + { + slider = reinterpret_cast(m_list_sliderSpinbox.at(i).first); + break; + } + if(slider == nullptr) + { + SANE_Int temp = value; + + m_list_IdValueTitle.append(QPair, QString>(QPair(id, temp), md5(opt->title))); + + SANE_Int method = 0; + m_saneAPI.sane_control_option_api(m_devHandle, id, SANE_ACTION_SET_VALUE, &temp, &method); + if((method & SANE_INFO_RELOAD_OPTIONS) == SANE_INFO_RELOAD_OPTIONS) + updateUIStatus(); + else if(value != temp) + { + disconnect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(slot_spinBoxClicked(int))); + spinBox->setValue(temp); + connect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(slot_spinBoxClicked(int))); + } + cur_scheme_->config_changed(id, (char*)&temp, sizeof(temp)); + }else + { + QSlider* slider_ = reinterpret_cast(slider); + slider_->setValue(spinBox->value()); + } +} + +void hg_settingdialog::slot_lineEditInput() +{ + QLineEdit* lineEdit = qobject_cast(sender()); + int id = lineEdit->property("controls_id").toInt(); + std::string lineEditCurrentText(lineEdit->text().toUtf8()); + + const SANE_Option_Descriptor* opt = nullptr; + for(int i = 0; i < m_list_getOpt.size(); i++) + if (m_list_getOpt.at(i).first == id) + { + opt = reinterpret_cast(m_list_getOpt.at(i).second); + break; + } + + m_list_IdValueTitle.append(QPair, QString>(QPair(id, &lineEditCurrentText.at(0)), md5(opt->title))); + + SANE_Int method = 0; + void *buf = NULL; + SANE_Int nv = 0; + if(opt->type == SANE_TYPE_INT) + { + nv = atoi(lineEditCurrentText.c_str()); + buf = &nv; + } + else if(opt->type == SANE_TYPE_FIXED) + { + nv = SANE_FIX(atof(lineEditCurrentText.c_str())); + buf = &nv; + } + else + { + buf = malloc(opt->size * 2 + 4); + strcpy((char*)buf, lineEditCurrentText.c_str()); + } + m_saneAPI.sane_control_option_api(m_devHandle, id, SANE_ACTION_SET_VALUE, buf, &method); + if((method & SANE_INFO_RELOAD_OPTIONS) == SANE_INFO_RELOAD_OPTIONS) + updateUIStatus(); + else if(method & SANE_INFO_INEXACT) + { + char mem[20], *v = mem; + if(opt->type == SANE_TYPE_INT) + sprintf(mem, "%d", nv); + else if(opt->type == SANE_TYPE_FIXED) + sprintf(mem, "%f", SANE_UNFIX(nv)); + else + v = (char*)buf; + lineEdit->setText(QString::fromStdString(v)); + } + + if(opt->type == SANE_TYPE_INT || opt->type == SANE_TYPE_FIXED) + { + cur_scheme_->config_changed(id, (char*)buf, sizeof(SANE_Int)); + } + else + { + std::string langCN(to_default_language((char*)buf, nullptr)); + cur_scheme_->config_changed(id, &langCN[0], langCN.length()); + free(buf); + } +} + +void hg_settingdialog::slot_buttonOkClicked() +{ + save_ = true; + close(); +} + +void hg_settingdialog::slot_buttonCancelClicked() +{ + close(); +} + +void hg_settingdialog::keyPressEvent(QKeyEvent *e) +{ + if (e->key() == Qt::Key_Escape) { + e->ignore(); + } + else { + QDialog::keyPressEvent(e); + } +} + +int hg_settingdialog::get_changed_items(void) +{ + return changed_count_; +} + +void hg_settingdialog::iniWrite(QString title, int id, QVariant value) +{ + (void)title; + (void)id; + (void)value; +// m_qstrFileName = QCoreApplication::applicationDirPath() + "/config.ini"; +// m_configIniWrite = new QSettings(m_qstrFileName, QSettings::IniFormat); +// m_configIniWrite->setIniCodec(QTextCodec::codecForName("UTF-8")); +// m_configIniWrite->setValue(title + "/id", id); +// m_configIniWrite->setValue(title + "/value", value); + +// delete m_configIniWrite; +// m_configIniWrite = nullptr; +} + +void hg_settingdialog::iniRead(QString title, int id, QWidget *w) +{ + (void)title; + (void)id; + (void)w; +// m_configIniRead = new QSettings("config.ini", QSettings::IniFormat); +// m_configIniRead->setIniCodec(QTextCodec::codecForName("UTF-8")); +// int id_ini = m_configIniRead->value(title + "/id").toInt(); +// QVariant value = m_configIniRead->value(title + "/value"); + +// if(id_ini == id) +// { +// if(typeid(*w) == typeid(QCheckBox)) +// reinterpret_cast(w)->setChecked(value.toBool()); + +// else if(typeid(*w) == typeid(QSlider)) +// reinterpret_cast(w)->setValue(value.toInt()); + +// else if(typeid(*w) == typeid(QSpinBox)) +// reinterpret_cast(w)->setValue(value.toInt()); + +// else if(typeid(*w) == typeid(QDoubleSpinBox)) +// reinterpret_cast(w)->setValue(value.toDouble()); + +// else if(typeid(*w) == typeid(QComboBox)) +// reinterpret_cast(w)->setCurrentText(value.toString()); +// } + +// delete m_configIniRead; +// m_configIniRead = nullptr; +} + +//生成UTF-8编码的MD5值 +QString hg_settingdialog::md5(QString key) +{ + QCryptographicHash md5(QCryptographicHash::Md5); + md5.addData(key.toUtf8()); + return QString(md5.result().toHex()); +} +const void* hg_settingdialog::find_option_description(int id) +{ + for(int i = 0; i < m_list_getOpt.size(); i++) + { + if (m_list_getOpt.at(i).first == id) + return reinterpret_cast(m_list_getOpt.at(i).second); + } + + return nullptr; +} +const void* hg_settingdialog::find_option_description(const std::string& title, int* id) +{ + for(int i = 0; i < m_list_getOpt.size(); i++) + { + std::string t((reinterpret_cast(m_list_getOpt.at(i).second))->name); + + if (title == t) + { + if(id) + *id = m_list_getOpt.at(i).first; + return reinterpret_cast(m_list_getOpt.at(i).second); + } + } + + return nullptr; +} + + +void hg_settingdialog::closeEvent(QCloseEvent* e) +{ + if(e->type() == QEvent::Close) // consider as cancel ... + { + if(save_) + save_scheme(); + else + cancel_setting(); + } + + e->accept(); +} + +bool hg_settingdialog::createMsgBoxUi(bool add, std::string &name) +{ + QString text(tr("Please select to overwrite the original configuration:")); + text += QString::fromStdString(name); + text += tr(",or add a new configuration"); + + QDialog *dlg = new QDialog(this); + dlg->setWindowTitle(tr("save the configuration")); + QLabel *label_question = new QLabel; + label_question->setText(text); + + QRadioButton *radioButtonCover = new QRadioButton; + radioButtonCover->setText(tr("cover original configuration:") + QString::fromStdString(name)); + radioButtonCover->setChecked(true); + add = false; + QRadioButton *radioButtonNew = new QRadioButton; + radioButtonNew->setText(tr("add new configuration")); + + QHBoxLayout *hLayoutName = new QHBoxLayout; + QLabel *label_name = new QLabel; + label_name->setText(tr("rename:")); + m_lineEdit_name = new QLineEdit; + std::string name2; + m_lineEdit_name->setText(QString::fromStdString(getCurUiShemeName(name2))); + + QSpacerItem *spacer1 = new QSpacerItem(20, 20, QSizePolicy::Expanding); + hLayoutName->addWidget(label_name); + hLayoutName->addWidget(m_lineEdit_name); + hLayoutName->addSpacerItem(spacer1); + label_name->setVisible(false); + m_lineEdit_name->setVisible(false); + + bool cover = true; + connect(radioButtonCover, &QRadioButton::clicked, this, [=, &add, &cover](){ + cover = true; + add = false; + label_name->setVisible(false); + m_lineEdit_name->setVisible(false); + }); + connect(radioButtonNew, &QRadioButton::clicked, this, [=, &add, &cover](){ + cover = false; + add = true; + label_name->setVisible(true); + m_lineEdit_name->setVisible(true); + + m_lineEdit_name->setFocus(); + QTimer::singleShot(0, m_lineEdit_name, &QLineEdit::selectAll); + }); + + QSpacerItem *spacer2 = new QSpacerItem(20, 20, QSizePolicy::Expanding); + QPushButton *pbtnOk = new QPushButton; + pbtnOk->setText(tr("ok")); + connect(pbtnOk, &QPushButton::clicked, this, [=, &name, &cover](){ + + QString text = m_lineEdit_name->text(); + static QRegularExpression re("\\s"); + text.remove(re);//Remove space + + name = text.toStdString(); + + if(name.empty()) + { + QMessageBox::information(this, tr("tips"), tr("scheme name cannot be empty")); + m_lineEdit_name->setText(QString::fromStdString(getCurUiShemeName(name))); + return; + } + + if (!cover) + { + std::vector now; + cur_cfg_->get_all_schemes(now); + for(auto& v: now) + { + if(v == name) + { + + QMessageBox::information(this, tr("tips"), tr("scheme name: ") + QString::fromStdString(name) + tr(" already exists")); + m_lineEdit_name->setText(QString::fromStdString(getCurUiShemeName(name))); + return; + } + } + } + + dlg->close(); + }); + + QHBoxLayout *hLayout_pbtnOk = new QHBoxLayout; + hLayout_pbtnOk->addSpacerItem(spacer2); + hLayout_pbtnOk->addWidget(pbtnOk); + + QVBoxLayout *vLayout = new QVBoxLayout; + vLayout->addWidget(label_question); + vLayout->addWidget(radioButtonCover); + vLayout->addWidget(radioButtonNew); + vLayout->addLayout(hLayoutName); + vLayout->addLayout(hLayout_pbtnOk); + dlg->setLayout(vLayout); + + dlg->exec(); + + return add; +} + +std::string hg_settingdialog::getCurUiShemeName(std::string name) +{ + std::string k(""), val(""); + int id = 0; + const SANE_Option_Descriptor* opt = nullptr; + + if (cur_scheme_->first_config(k, val)) + { + int count = 0; + do + { + id = cur_scheme_->id_from_name(k.c_str()); + opt = id == -1 ? nullptr : m_saneAPI.sane_get_option_descriptor_api(m_devHandle, id); + if (opt) + { + if (count++) + name += " + "; + + if (opt->type == SANE_TYPE_STRING) + name += from_default_language(val.c_str(), nullptr); + else + { + name += opt->title; + if (opt->type == SANE_TYPE_BOOL) + { + name += std::string("("); + if (*(SANE_Bool*)&val[0] == SANE_TRUE) + name += "true)"; + else + name += "false)"; + } + else if (opt->type == SANE_TYPE_INT) + { + char buf[128] = { 0 }; + sprintf(buf, "(%d)", *(int*)&val[0]); + name += buf; + } + else if (opt->type == SANE_TYPE_FIXED) + { + char buf[128] = { 0 }; + sprintf(buf, "(%.4f)", SANE_UNFIX(*(SANE_Fixed*)&val[0])); + name += buf; + } + } + } + } while (count < 3 && cur_scheme_->next_config(k, val)); + } + return name; +} + +void hg_settingdialog::save_scheme(void) +{ + std::string name(cur_scheme_->get_scheme_name()); + + bool add = name.empty(); + + if(add) + { + name = getCurUiShemeName(name); + } + else + { + int items = 0; + add = cur_scheme_->has_changed(&items); + if(add) + { + if(items == 0) // while shemes is default + { + cur_cfg_->select_scheme(nullptr); + return; + } + else + add = createMsgBoxUi(add, name); + } + } + if(add) + { + if(name.empty() && cur_scheme_->get_scheme_name().empty()) + { + cur_scheme_->end_setting(true); + return; + } + + gb::sane_config_schm* cp = cur_scheme_->copy(); + + cur_scheme_->end_setting(true); + cur_scheme_->release(); + cur_scheme_ = cp; + + size_t pos = name.rfind('-'); + int ind = 0; + char append[20] = {0}; + + if(pos != std::string::npos) + { + ind = atoi(name.c_str() + pos + 1); + if(ind > 0) + { + name.erase(pos); + sprintf(append, "-%d", ++ind); + } + } + while(!cur_cfg_->add_scheme(cur_scheme_, (name + append).c_str())) + { + sprintf(append, "-%d", ++ind); + } + } + else + { + cur_scheme_->end_setting(false); + } + + cur_cfg_->select_scheme(cur_scheme_->get_scheme_name().c_str()); + + cur_cfg_->save(); +} +void hg_settingdialog::cancel_setting(void) +{ + // restore changed value ... + cur_scheme_->end_setting(true); + dev_que::apply_scheme(&m_saneAPI, m_devHandle, cur_scheme_); +} + +void hg_settingdialog::getAppVersion() +{ + SANE_About *about = nullptr; + unsigned int len = 0; + std::string versionNum; + if (m_saneAPI.sane_io_control_api(m_devHandle, 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 (m_saneAPI.sane_io_control_api(m_devHandle, IO_CTRL_CODE_ABOUT_INFO, about, &len) == SANE_STATUS_GOOD) + { + versionNum = about->version; + } + } + } +} +void hg_settingdialog::apply_current_scheme(void) +{ + dev_que::apply_scheme(&m_saneAPI, m_devHandle, cur_scheme_); +} +std::string sane_val_to_string(const char* val, SANE_Value_Type type) +{ + char buf[128] = {0}; + std::string ret(""); + + switch(type) + { + case SANE_TYPE_BOOL: + ret = *(SANE_Bool*)val == SANE_TRUE ? "true" : "false"; + break; + case SANE_TYPE_INT: + sprintf(buf, "%d", *(int*)val); + ret = buf; + break; + case SANE_TYPE_FIXED: + sprintf(buf, "%.4f", SANE_UNFIX(*(SANE_Fixed*)val)); + ret = buf; + break; + default: + ret = val; + break; + } + + return ret; +} +void hg_settingdialog::on_current_scheme_changed() +{ + QString scheme(comb_->currentText()); + bool enabled = false; + gb::sane_config_schm *schm = cur_cfg_->get_scheme(scheme.toStdString().c_str()); + + if(schm) + enabled = true; + + rename_->setEnabled(enabled); + apply_->setEnabled(enabled); + del_this_->setEnabled(enabled); + del_all_->setEnabled(enabled); + 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; + + QString info(tr("")); + std::string name(""), val(""); + if(schm && schm->first_config(name, val)) + { + do + { + QString title; + SANE_Value_Type type = SANE_TYPE_STRING; + for (int ii = 0; ii < m_list_defaultOptions.size(); ii++) + { + const SANE_Option_Descriptor* opt = reinterpret_cast(m_list_defaultOptions.at(ii).first); + if(strcmp(opt->name, name.c_str()) == 0) + { + title = QString::fromStdString(opt->title); + type = opt->type; + if(type == SANE_TYPE_STRING) + val = from_default_language(val.c_str(), nullptr); + break; + } + } + + if(title.length()) + { + info += tr("
") + title + tr(":
"); + info += tr("

") + QString::fromStdString(sane_val_to_string(val.c_str(), type)) + tr("

"); + } + else { + if(val.length() == sizeof(SANE_Gamma)) + memcpy(&m_gammaData, val.c_str(), sizeof(SANE_Gamma)); + } + }while(schm->next_config(name, val)); + } + if(schm) + schm->release(); + + sketch_->setHtml(info); +} +void hg_settingdialog::slot_pushButton_scheme_management(void) +{ + QPushButton* btn = qobject_cast(sender()); + + if(btn == rename_) + { + int id = 0; + QString text(find_current_scheme_menu(&id)); + if(!text.isEmpty() && id >= 0) + { + Dialog_Input dlg; + + dlg.init_value(text); + dlg.setWindowTitle(tr("configuration scheme name change")); + if(dlg.exec() && text != dlg.get_inputting_value()) + { + std::vector now; + std::string str = dlg.get_inputting_value().toStdString(); + + cur_cfg_->get_all_schemes(now); + for(auto& v: now) + { + if(v == str) + { + QMessageBox::information(this, tr("tips"), tr("scheme name: ") + QString::fromStdString(str) + tr(" already exists")); + return; + } + } + disconnect(comb_, SIGNAL(currentTextChanged(const QString)), this, SLOT(on_current_scheme_changed())); + comb_->removeItem(id); + comb_->insertItem(id, QString::fromStdString(str)); + comb_->setCurrentIndex(id); + connect(comb_, SIGNAL(currentTextChanged(const QString)), this, SLOT(on_current_scheme_changed())); + + cur_cfg_->rename_scheme(text.toStdString().c_str(), str.c_str()); + cur_cfg_->save(); + changed_count_++; + } + } + } + else if(btn == apply_) + { + QString text(find_current_scheme_menu()); + gb::sane_config_schm *cur = nullptr; + + cur_cfg_->select_scheme(text.toStdString().c_str()); + cur = cur_cfg_->get_scheme(); + if(!cur) + cur = new gb::sane_config_schm(); + cur->copy_default_value(cur_scheme_); + cur_scheme_->end_setting(true); + cur_scheme_->release(); + cur_scheme_ = cur; + cur_scheme_->begin_setting(); + + apply_current_scheme(); + updateUIStatus(); + changed_count_++; + } + else if(btn == del_this_) + { + int id = -1; + QString text(find_current_scheme_menu(&id)); + + if(text.isEmpty()) + return; + + QMessageBox msg(QMessageBox::Question, tr("be sure to delete the configuration"), + tr("Are you sure you want to delete the configuration \"") + text + tr("\" ?"), QMessageBox::Yes | QMessageBox::No, this); + msg.exec(); + if (msg.clickedButton() != msg.button(QMessageBox::Yes)) + return; + + gb::sane_config_schm *sch = cur_cfg_->get_scheme(text.toStdString().c_str()); + cur_cfg_->remove_scheme(text.toStdString().c_str()); + comb_->removeItem(id); + sch->release(); + if(sch == cur_scheme_) + { + restore_2_default_settings(); + updateUIStatus(); + } + + on_current_scheme_changed(); + changed_count_++; + cur_cfg_->save(); + } + else if(btn == del_all_) + { + QMessageBox msg(QMessageBox::Question, tr("be sure to delete the configuration"), + tr("Are you sure you want to delete the configuration?"), QMessageBox::Yes | QMessageBox::No, this); + msg.exec(); + if (msg.clickedButton() != msg.button(QMessageBox::Yes)) + return; + + restore_2_default_settings(); + updateUIStatus(); + comb_->clear(); + changed_count_++; + cur_cfg_->remove_all_schemes(); + cur_cfg_->save(); + } +} +void hg_settingdialog::restore_2_default_settings(void) +{ + cur_scheme_->end_setting(true); + cur_cfg_->select_scheme(nullptr); + dev_que_.apply_scheme(&m_saneAPI, nullptr); + cur_cfg_->save(); + + gb::sane_config_schm *s = new gb::sane_config_schm(); + s->copy_default_value(cur_scheme_); + cur_scheme_->release(); + cur_scheme_ = s; + cur_scheme_->begin_setting(); + + on_current_scheme_changed(); +} diff --git a/modules/saneui/hg_settingdialog.h b/modules/saneui/hg_settingdialog.h new file mode 100644 index 00000000..fb4c0e35 --- /dev/null +++ b/modules/saneui/hg_settingdialog.h @@ -0,0 +1,141 @@ +#ifndef HG_SETTING_DIALOG_H +#define HG_SETTING_DIALOG_H + +#include +#include +#include +#include "sane/sane_ex.h" +#include "cfg/gb_json.h" +#include "device_menu.h" + +class hg_settingdialog : public QDialog +{ + Q_OBJECT + + int changed_count_; + bool save_; + bool clicked_gamma_; + dev_que dev_que_; + gb::scanner_cfg *cur_cfg_; + gb::sane_config_schm *cur_scheme_; + + void refresh_control_value(int op_id); + void on_select_scheme(bool apply_to_dev = true); + QString gen_gamma_file_path(void); + + QMenu *top_menu_; + QLineEdit *edit_name_; + QPushButton *rename_; + QPushButton *apply_; + QPushButton *del_this_; + QPushButton *del_all_; + QLabel *custom_area_lable_; + QPushButton *btn_cut_area_; + QPushButton *btn_gamma_; + QTextEdit *sketch_; + QLineEdit *m_lineEdit_name; + void create_scheme_management_ui(QVBoxLayout* layout); + QString find_current_scheme_menu(int *scheme_id = nullptr); + + static std::string property_combox_data_type_; + enum _cbox_type + { + COMBO_VAL_STRING = 0, + COMBO_VAL_INT, + COMBO_VAL_FLOAT, + }; + +public: + explicit hg_settingdialog(SANEAPI* saneApi, SANE_Handle handle, const char *scanner_name, QWidget *parent = nullptr); + ~hg_settingdialog(); + +public: + void initUi(); + void updateOpt(); + void createUI(); + void updateUIStatus(); + QVector find_control(int opt_num); + void keyPressEvent(QKeyEvent *e); + int get_changed_items(void); + +private: + SANEAPI m_saneAPI; + SANE_Handle m_devHandle; + +private: + QString m_qstrFileName; + QSettings *m_configIniWrite; + QSettings *m_configIniRead; + +private: + void iniWrite(QString title, int id, QVariant value); + void iniRead(QString title, int id, QWidget *w); + QString md5(QString key); + 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 + + virtual void closeEvent(QCloseEvent* e); + bool createMsgBoxUi(bool add, std::string &name); + std::string getCurUiShemeName(std::string name); + void save_scheme(void); + void cancel_setting(void); + void getAppVersion(); + void apply_current_scheme(void); + +private: + QVector, QString>> m_list_IdValueTitle; + QVector> m_list_defaultOptions; // default values of device + QVector> m_list_sliderSpinbox; + QVector> m_list_getOpt; + QVector m_list_deviceNames; + QVector m_list_widgets; + +private slots: + void slot_checkedClicked(); + void slot_sliderClicked(int value); + void slot_spinBoxClicked(int value); + void slot_doubleSpinboxClicked(double value); + void slot_string_list_comboBoxClicked(); + void slot_pushButtonClicked(); + void slot_cutButtonClicked(); + void slot_gammaButtonClicked(); + void slot_word_list_comboBoxClicked(int value); + void slot_lineEditInput(); + void slot_buttonOkClicked(); + void slot_buttonCancelClicked(); + void slot_pushButton_scheme_management(void); + void on_current_scheme_changed(void); + void restore_2_default_settings(void); + +private: + int m_dpiId; + int m_dpiValue; + int m_paperSizeId; + QString m_paperSizeValue; + int m_cutLeftId; + int m_cutTopId; + int m_cutRightId; + int m_cutBottomId; + double m_cutWidth; // 单位是毫米 + double m_cutHeight; // 单位是毫米 + double m_cutLeftValue; // 单位是毫米 + double m_cutTopValue; // 单位是毫米 + double m_cutRightValue; // 单位是毫米 + double m_cutBottomValue; // 单位是毫米 + + int m_colorModeId; + QString m_colorModeValue; + SANE_Gamma m_gammaData; + QComboBox *comb_; +}; + +#endif // HG_SETTING_DIALOG_H + + + + + + + + + diff --git a/modules/saneui/setpicclrtool.cpp b/modules/saneui/setpicclrtool.cpp new file mode 100644 index 00000000..78597d89 --- /dev/null +++ b/modules/saneui/setpicclrtool.cpp @@ -0,0 +1,315 @@ +#include "setpicclrtool.h" +#include "ui_setpicclrtool.h" +#include "widget.h" +#include +#include + +setPicClrTool::setPicClrTool(QWidget *parent) : + QDialog(parent), + ui(new Ui::setPicClrTool) +{ + ui->setupUi(this); + setMouseTracking(true); + ui->inputEdt->setEnabled(false); + ui->outputEdt->setEnabled(false); + ui->inputEdt->setValidator(new QIntValidator(0, 255, this)); + ui->outputEdt->setValidator(new QIntValidator(0, 255, this)); + ui->widget->setFocus(Qt::MouseFocusReason); + connect(ui->widget,SIGNAL(mouseCoordSig(QPoint)),this,SLOT(mouseCoordSlot(QPoint))); + connect(ui->widget,SIGNAL(dragPointChecked(bool)),this,SLOT(lineEditEnable(bool))); + connect(ui->widget,SIGNAL(lineChangeSig()),this,SLOT(lineChangeSlot())); +} + +setPicClrTool::~setPicClrTool() +{ + delete ui; +} + +void setPicClrTool::getGrayTable(uchar *table, size_t length) +{ + QVector gray = getGrayALLPoint(); + for (size_t i = 0; i < length; i++) + table[i] = static_cast(gray[static_cast(i)]); +} + +void setPicClrTool::getRGBTable(uchar *table, size_t length) +{ + if (length != 768) + throw "length is not 768."; + + QVector rgb = getRgbALLPoint(); + QVector red = getRedALLPoint(); + QVector green = getGreenALLPoint(); + QVector blue = getBlueALLPoint(); + + + for (size_t i = 0; i < 256; i++) + { + //if (i == 255) + // int a = 0; + //table member order is B\G\R + table[i * 3 + 0] = static_cast(blue[rgb[static_cast(i)]]); + table[i * 3 + 1] = static_cast(green[rgb[static_cast(i)]]); + table[i * 3 + 2] = static_cast(red[rgb[static_cast(i)]]); + } +} + +//void setPicClrTool::setGrayTable(const uchar *table, size_t length) +//{ +// QVector gray; +// for (size_t i = 0; i < length; i++) +// gray[static_cast(i)] = int(table[i]); +// //ui->widget->setGrayALLPoint(gray); +//} + +//void setPicClrTool::setRGBTable(const uchar *table, size_t length) +//{ +// QVector rgb; +// QVector red; +// QVector green; +// QVector blue; +// for(int i = 0; i < 256; i++){ +// rgb.append(i); +// } +// for (size_t i = 0; i < length; i++){ +// red.append(int(table[i * 3 + 0])); +// green.append(int(table[i * 3 + 1])); +// blue.append(int(table[i * 3 + 2])); +// } + +//} + +void setPicClrTool::setColorMode(int colorMode) +{ + QVariant v(6); + if(colorMode == 0) + { + ui->colorSetCmb->setItemData(1,v,Qt::UserRole - 1); + } + else + { + ui->comboBox->setItemData(2,v,Qt::UserRole - 1); + ui->colorSetCmb->setItemData(0,v,Qt::UserRole - 1); + ui->colorSetCmb->setItemData(2,v,Qt::UserRole - 1); + ui->colorSetCmb->setItemData(3,v,Qt::UserRole - 1); + ui->colorSetCmb->setItemData(4,v,Qt::UserRole - 1); + ui->colorSetCmb->setCurrentIndex(1); + } +} + +QVector > setPicClrTool::getRGBKeyTable() +{ + QVector> plv; + plv.append(getRgbKeyPoint()); + plv.append(getRedKeyPoint()); + plv.append(getGreenKeyPoint()); + plv.append(getBlueKeyPoint()); + return plv; +} + +void setPicClrTool::setRGBKeyTable(QVector > &plv) +{ + setRgbKeyPoint(plv[0]); + setRedKeyPoint(plv[1]); + setGreenKeyPoint(plv[2]); + setBlueKeyPoint(plv[3]); +} + +QList setPicClrTool::getGrayKeyTable() +{ + return getGrayKeyPoint(); +} + +void setPicClrTool::setGrayKeyTable(QList &plv) +{ + setGrayKeyPoint(plv); +} + +QVector setPicClrTool::getRgbALLPoint() +{ + return ui->widget->getRgbALLPoint(); +} + +QList setPicClrTool::getRgbKeyPoint() const +{ + qDebug() << "setRgb" << ui->widget->getRgbKeyPoint(); + return ui->widget->getRgbKeyPoint(); +} + +void setPicClrTool::setRgbKeyPoint(const QList &pVec) +{ + qDebug() << "setRgb" << pVec; + ui->widget->setRgbKeyPoint(pVec); +} + +QList setPicClrTool::getRedKeyPoint() const +{ + return ui->widget->getRedKeyPoint(); +} + +void setPicClrTool::setRedKeyPoint(const QList &pVec) +{ + ui->widget->setRedKeyPoint(pVec); +} + +QList setPicClrTool::getBlueKeyPoint() const +{ + return ui->widget->getBlueKeyPoint(); +} + +void setPicClrTool::setBlueKeyPoint(const QList &pVec) +{ + ui->widget->setBlueKeyPoint(pVec); +} + +QList setPicClrTool::getGreenKeyPoint() const +{ + return ui->widget->getGreenKeyPoint(); +} + +void setPicClrTool::setGreenKeyPoint(const QList &pVec) +{ + ui->widget->setGreenKeyPoint(pVec); +} + +QList setPicClrTool::getGrayKeyPoint() const +{ + return ui->widget->getGrayKeyPoint(); +} + +void setPicClrTool::setGrayKeyPoint(const QList &pVec) +{ + ui->widget->setGrayKeyPoint(pVec); +} + +QVector setPicClrTool::getRedALLPoint() +{ + return ui->widget->getRedALLPoint(); +} + +QVector setPicClrTool::getBlueALLPoint() +{ + return ui->widget->getBlueALLPoint(); +} + +QVector setPicClrTool::getGreenALLPoint() +{ + return ui->widget->getGreenALLPoint(); +} + +QVector setPicClrTool::getGrayALLPoint() +{ + return ui->widget->getGrayALLPoint(); +} + +void setPicClrTool::mouseCoordSlot(QPoint pos) +{ + ui->inputEdt->setText(QString::number(pos.x())); + ui->outputEdt->setText(QString::number(pos.y())); +} + +void setPicClrTool::lineEditEnable(bool a) +{ + ui->inputEdt->setEnabled(a); + ui->outputEdt->setEnabled(a); +} + +void setPicClrTool::lineChangeSlot() +{ + ui->comboBox->setCurrentIndex(0); +} + +void setPicClrTool::on_colorSetCmb_currentIndexChanged(int index) +{ + (void)index; + /* switch(index){ + case RED: + ui->widget->updateCurLinePnt(RED); + break; + case GREEN: + ui->widget->updateCurLinePnt(GREEN); + break; + case BLUE: + ui->widget->updateCurLinePnt(BLUE); + break; + case RGB: + ui->widget->updateCurLinePnt(RGB); + break; + case GRAY: + ui->widget->updateCurLinePnt(GRAY); + break; + }*/ +} + +void setPicClrTool::on_comboBox_currentIndexChanged(int index) +{ + if(index == 0){ + ui->widget->initAllLstPnt(); + ui->widget->updateCurLinePnt(ui->colorSetCmb->currentIndex()); + return ; + } + ui->widget->initAllLstPnt(); + if(index == 1){ + rgbLine.clear(); + rgbLine.append(QPoint(0,255)); + rgbLine.append(QPoint(255,0)); + ui->widget->setLstPnt_RGB(rgbLine); + }else if(index == 2){ + redLine.clear(); + redLine.append(QPoint(33,255)); + redLine.append(QPoint(185,0)); + redLine.append(QPoint(119,127)); + greenLine.clear(); + greenLine.append(QPoint(28,255)); + greenLine.append(QPoint(132,0)); + greenLine.append(QPoint(77,127)); + blueLine.clear(); + blueLine.append(QPoint(25,255)); + blueLine.append(QPoint(108,0)); + blueLine.append(QPoint(60,127)); + ui->widget->setLstPnt_RED(redLine); + ui->widget->setLstPnt_GREEN(greenLine); + ui->widget->setLstPnt_BLUE(blueLine); + }else if(index == 4){ + rgbLine.clear(); + rgbLine.append(QPoint(0,0)); + rgbLine.append(QPoint(255,255)); + rgbLine.append(QPoint(103,125)); + ui->widget->setLstPnt_RGB(rgbLine); + }else if(index == 3){ + rgbLine.clear(); + rgbLine.append(QPoint(0,0)); + rgbLine.append(QPoint(255,255)); + rgbLine.append(QPoint(130,101)); + ui->widget->setLstPnt_RGB(rgbLine); + } + ui->widget->updateCurLinePnt(ui->colorSetCmb->currentIndex()); +} + +void setPicClrTool::on_inputEdt_textChanged(const QString &arg1) +{ + ui->widget->setXCoorVal(arg1.toInt()); +} + +void setPicClrTool::on_outputEdt_textChanged(const QString &arg1) +{ + ui->widget->setYCoorVal(arg1.toInt()); +} + +void setPicClrTool::on_pushButton_clicked() +{ + ui->widget->initSelectColLine(ui->colorSetCmb->currentIndex()); +} + +void setPicClrTool::on_buttonBox_accepted() +{ + //close(); + accept(); +} + +void setPicClrTool::on_buttonBox_rejected() +{ + ui->widget->initAllLstPnt(); + //close(); + reject(); +} diff --git a/modules/saneui/setpicclrtool.h b/modules/saneui/setpicclrtool.h new file mode 100644 index 00000000..59c4c25b --- /dev/null +++ b/modules/saneui/setpicclrtool.h @@ -0,0 +1,82 @@ +#ifndef SETPICCLRTOOL_H +#define SETPICCLRTOOL_H + +//#include "colorlinesetdef.h" +#include + +namespace Ui { +class setPicClrTool; +} + +class setPicClrTool : public QDialog +{ + Q_OBJECT + +public: + explicit setPicClrTool(QWidget *parent = nullptr); + ~setPicClrTool(); + + void getGrayTable(uchar* table, size_t length = 256); + + void getRGBTable(uchar* table, size_t length = 768); + +// void setGrayTable(const uchar* table, size_t length = 256); + +// void setRGBTable(const uchar* table, size_t length = 768); + + void setColorMode(int colorMode); + + QVector> getRGBKeyTable(); + void setRGBKeyTable(QVector>& plv); + QList getGrayKeyTable(); + void setGrayKeyTable(QList &plv); + + +private: + QVector getRgbALLPoint(); + QVector getRedALLPoint(); + QVector getBlueALLPoint(); + QVector getGreenALLPoint(); + QVector getGrayALLPoint(); + + QList getRgbKeyPoint()const; + void setRgbKeyPoint(const QList& pVec); + QList getRedKeyPoint()const; + void setRedKeyPoint(const QList& pVec); + QList getBlueKeyPoint()const; + void setBlueKeyPoint(const QList& pVec); + QList getGreenKeyPoint()const; + void setGreenKeyPoint(const QList& pVec); + QList getGrayKeyPoint()const; + void setGrayKeyPoint(const QList& pVec); + +private slots: + void mouseCoordSlot(QPoint);//set QLineEdit value by QPoint setting + void lineEditEnable(bool);//set 2 LineEdit enable status + void lineChangeSlot(); + + void on_colorSetCmb_currentIndexChanged(int index); + + void on_comboBox_currentIndexChanged(int index); + + void on_inputEdt_textChanged(const QString &arg1); + + void on_outputEdt_textChanged(const QString &arg1); + + void on_pushButton_clicked(); + + void on_buttonBox_accepted(); + + void on_buttonBox_rejected(); + +private: + Ui::setPicClrTool *ui; + QList linePoint; + QList greenLine; + QList redLine; + QList blueLine; + QList rgbLine; + QList grayLine; +}; + +#endif // SETPICCLRTOOL_H diff --git a/modules/saneui/setpicclrtool.ui b/modules/saneui/setpicclrtool.ui new file mode 100644 index 00000000..5ba412a6 --- /dev/null +++ b/modules/saneui/setpicclrtool.ui @@ -0,0 +1,167 @@ + + + setPicClrTool + + + + 0 + 0 + 259 + 341 + + + + 自定义色调曲线 + + + + + + + + + 自定义 + + + + + 负片(RGB) + + + + + 彩色负片(RGB) + + + + + 较暗(RGB) + + + + + 较亮(RGB) + + + + + + + + + + + + false + + + + RGB + + + + + + + + + + + + + + + + + + + + 绿 + + + + + + + + 初始化 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + true + + + Qt::StrongFocus + + + + + + + + + 输入: + + + + + + + true + + + + + + + 输出: + + + + + + + true + + + + + + + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + Widget + QWidget +
widget.h
+ 1 +
+
+ + +
diff --git a/modules/saneui/widget.cpp b/modules/saneui/widget.cpp new file mode 100644 index 00000000..71c943bf --- /dev/null +++ b/modules/saneui/widget.cpp @@ -0,0 +1,855 @@ +#include "widget.h" +#include "ui_widget.h" +#include "gaosixy.h" +#include +#include +#include +#include +using namespace std; + + +enum COLOR_TPYE +{ + RGB, + GRAY, + RED, + BLUE, + GREEN +}; + +Widget::Widget(QWidget *parent) : + QWidget(parent), + ui(new Ui::Widget) +{ + ui->setupUi(this); + setWindowTitle(tr("zuobiaozhou")); //设置标题栏标题 + //resize(300,300); //设置窗口初始大小 + //ui->table->setWindowFlags(Qt::WindowStaysOnTopHint); + initAllLstPnt(); + initInterface(); +} + +Widget::~Widget() +{ + delete ui; +} + +void Widget::setLstPnt_RGB(const QList &plst) +{ + rgbLine = QList(plst); +} + +QList Widget::getLstPnt_RGB() const +{ + return rgbLine; +} + +void Widget::setLstPnt_RED(const QList &plst) +{ + redLine = QList(plst); +} + +void Widget::setLstPnt_BLUE(const QList &plst) +{ + blueLine = QList(plst); +} + +QList Widget::getLstPnt_BLUE() const +{ + return blueLine; +} + +void Widget::setLstPnt_GREEN(const QList &plst) +{ + greenLine = QList(plst); +} + +QList Widget::getLstPnt_GREEN() const +{ + return greenLine; +} + +void Widget::setLstPnt_GRAY(const QList &plst) +{ + grayLine = QList(plst); +} + +QList Widget::getLstPnt_GRAY() const +{ + return grayLine; +} + +QVector Widget::getRgbALLPoint() +{ + return rgbALLPoint; +} + +QList Widget::getRgbKeyPoint() const +{ + return rgbLine; +} + +void Widget::setRgbKeyPoint(const QList &pLst) +{ + if(pLst.size() > 4) return; + rgbLine = QList(pLst); + pointLst.clear(); + pointLst = QList(rgbLine); + drawLineFromPoint(rgbLine, RGB); + update(); +} + +QVector Widget::getRedALLPoint() +{ + return redALLPoint; +} + +QList Widget::getRedKeyPoint() const +{ + return redLine; +} + +void Widget::setRedKeyPoint(const QList &pLst) +{ + if(pLst.size() > 4) return; + redLine = QList(pLst); + drawLineFromPoint(redLine, RED); + update(); +} + +QVector Widget::getBlueALLPoint() +{ + return blueALLPoint; +} + +QList Widget::getBlueKeyPoint() const +{ + return blueLine; +} + +void Widget::setBlueKeyPoint(const QList &pLst) +{ + if(pLst.size() > 4) return; + blueLine = QList(pLst); + drawLineFromPoint(blueLine, BLUE); + update(); +} + +QVector Widget::getGreenALLPoint() +{ + return greenALLPoint; +} + +QList Widget::getGreenKeyPoint() const +{ + return greenLine; +} + +void Widget::setGreenKeyPoint(const QList &pLst) +{ + if(pLst.size() > 4) return; + greenLine = QList(pLst); + drawLineFromPoint(greenLine, GREEN); + update(); +} + +QVector Widget::getGrayALLPoint() +{ + return grayALLPoint; +} + +QList Widget::getGrayKeyPoint() const +{ + return grayLine; +} + +void Widget::setGrayKeyPoint(const QList &pLst) +{ + if(pLst.size() > 4) return; + grayLine = QList(pLst); + pointLst.clear(); + pointLst = QList(grayLine); + drawLineFromPoint(grayLine, GRAY); + update(); +} + +void Widget::initAllLstPnt() +{ + pointLst.clear(); + pointLst.append(QPoint(0,0)); + pointLst.append(QPoint(255,255)); + redLine.clear(); + redLine.append(QPoint(0,0)); + redLine.append(QPoint(255,255)); + blueLine.clear(); + blueLine.append(QPoint(0,0)); + blueLine.append(QPoint(255,255)); + greenLine.clear(); + greenLine.append(QPoint(0,0)); + greenLine.append(QPoint(255,255)); + rgbLine.clear(); + rgbLine.append(QPoint(0,0)); + rgbLine.append(QPoint(255,255)); + grayLine.clear(); + grayLine.append(QPoint(0,0)); + grayLine.append(QPoint(255,255)); + drawLineFromPoint(redLine, RED); + drawLineFromPoint(rgbLine, RGB); + drawLineFromPoint(greenLine, GREEN); + drawLineFromPoint(blueLine, BLUE); + drawLineFromPoint(grayLine, GRAY); +} + +void Widget::initInterface() +{ + color = Qt::gray; + selectCol = RGB; + leftMouseMv = false; + newPoint = false; + clickLine = false; + dragPoint = -1; + setMouseTracking(true); + ui->widget_2->setStyleSheet("QWidget{background-color:qlineargradient(" + "spread:pad, x1:0, y1:0, x2:1, y2:0, " + "stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 255, 255, 255))}"); + ui->widget->setStyleSheet("QWidget{background-color:qlineargradient(" + "spread:pad, x1:0, y1:1, x2:0, y2:0, " + "stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 255, 255, 255))}"); +} + +void Widget::paintEvent(QPaintEvent *) +{ + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing,true); //开启抗锯齿 + painter.translate(ui->widget->width(),ui->widget->height()); //坐标系统平移变换,把原点平移 + painter.scale(ui->table->width() / 258.0,ui->table->height() / 258.0); //坐标系统比例变换,使绘制的图形随窗口的放大而放大 + painter.scale(1,-1); + + drawCoordinate(painter); + drawBackColorBySlc(painter); + drawCoorScale(painter); + drawCurveByColor(painter); + drawAllPoint(painter); + + if(dragPoint < 0){ + setMouseTracking(true); + emit dragPointChecked(false); + } + painter.end(); +} + +void Widget::mousePressEvent(QMouseEvent *event) +{ + int x = (event->x() - ui->widget->width())*258/ui->table->width(); + int y = (height() - event->y()-ui->widget_2->height())*258/ui->table->height(); + //qDebug() << x << y; + if(event->button() == Qt::LeftButton){ + newPoint = false; + dragPoint = -1; + clickLine = false; + for(int i = 0; i < linePoint.size();i++){ + int px = linePoint.at(i).x(); + int py = linePoint.at(i).y(); + if(qAbs(x-px) <= 6 && qAbs(y-py) <= 6) + { + newPoint = true; + for(int j = 0; j < pointLst.size(); j++){ + int lx = pointLst.at(j).x(); + int ly = pointLst.at(j).y(); + if(qAbs(x-lx) <= 6 && qAbs(y-ly) <= 6){ + dragPoint = j; + clickLine = true; + leftMouseMv = true; + newPoint = false; + emit dragPointChecked(true); + setMouseTracking(false); + update(); + break; + } + } + if(newPoint && pointLst.size() < 4 && x > pointLst.at(0).x() && x < pointLst.at(1).x()){ + pointLst.append(QPoint(x,y)); + dragPoint = pointLst.size()-1; + leftMouseMv = true; + clickLine = true; + emit dragPointChecked(true); + setMouseTracking(false); + update(); + } + } + } + } + else if(event->button() == Qt::RightButton){ + for(int j = 0; j < pointLst.size(); j++){ + int lx = pointLst.at(j).x(); + int ly = pointLst.at(j).y(); + if(qAbs(x-lx) <= 7 && qAbs(y-ly) <= 5){ + if(j > 1) + pointLst.removeAt(j); + if(j == dragPoint){ + dragPoint = -1; + emit dragPointChecked(false); + }else if(j > dragPoint){ + dragPoint = dragPoint; + }else { + dragPoint = dragPoint-1; + } + update(); + break; + } + } + } + if(!clickLine){ + dragPoint = -1; + emit dragPointChecked(false); + setMouseTracking(true); + update(); + } + emit mouseCoordSig(QPoint(x,y)); +} + +void Widget::mouseMoveEvent(QMouseEvent *event) +{ + int x = (event->x() - ui->widget->width())*258/ui->table->width(); + int y = (height() - event->y()-ui->widget_2->height())*258/ui->table->height(); + if(x < 0) x = 0; + if(y < 0) y = 0; + if(x >= 255) x = 255; + if(y >= 255) y = 255; + //qDebug() << x << y; + if(leftMouseMv && dragPoint >= 0) + { + if(pointLst[dragPoint] != pointLst.at(0) && pointLst[dragPoint] != pointLst.at(1)){ + if(x <= pointLst.at(0).x()) x = pointLst.at(0).x() + 1; + if(x >= pointLst.at(1).x()) x = pointLst.at(1).x() - 1; + + if(pointLst.size() == 4){ + if(dragPoint == 2){ + if(pointLst[2].x() > pointLst[3].x() && x <= pointLst[3].x()) + x = pointLst[3].x() + 1; + if(pointLst[2].x() < pointLst[3].x() && x >= pointLst[3].x()) + x = pointLst[3].x() - 1; + } + else if(dragPoint == 3){ + if(pointLst[2].x() < pointLst[3].x() && x <= pointLst[2].x()) + x = pointLst[2].x() + 1; + if(pointLst[2].x() > pointLst[3].x() && x >= pointLst[2].x()) + x = pointLst[2].x() - 1; + } + } + } + else if(pointLst[dragPoint] == pointLst.at(0)){ + int min = 999; + for(int i = 1; i < pointLst.size(); i++){ + if(min > pointLst[i].x()) min = pointLst[i].x(); + } + if(x >= min) x = min-1; + } + else if(pointLst[dragPoint] == pointLst.at(1)){ + if(pointLst.size() > 2){ + int max = 0; + for(int i = 2; i < pointLst.size(); i++){ + if(max < pointLst[i].x()) max = pointLst[i].x(); + } + if(x <= max) x = max+1; + } + else if(pointLst.size() <= 2) + if(x <= pointLst.at(0).x()) x = pointLst.at(0).x()+1; + } + pointLst[dragPoint].setX(x); + pointLst[dragPoint].setY(y); + emit lineChangeSig(); + update(); + } + emit mouseCoordSig(QPoint(x,y)); +} + +void Widget::mouseReleaseEvent(QMouseEvent *) +{ + leftMouseMv = false; +} + +void Widget::enterEvent(QEvent *) +{ + setFocus(Qt::MouseFocusReason); +} + +void Widget::leaveEvent(QEvent *) +{ + if(dragPoint < 0) + emit mouseLeaveSig(); +} + +void Widget::setHist_RGB(const QVector &hist) +{ + rgbBackColor = QVector(hist); +} + +QVector Widget::getHist_RED() const +{ + return redBackColor; +} + +void Widget::setHist_RED(const QVector &hist) +{ + redBackColor = QVector(hist); +} + +QVector Widget::getHist_RGB() const +{ + return rgbBackColor; +} + +void Widget::setHist_GREEN(const QVector &hist) +{ + greenBackColor = QVector(hist); +} + +QVector Widget::getHist_GREEN() const +{ + return greenBackColor; +} + +void Widget::setHist_BLUE(const QVector &hist) +{ + blueBackColor = QVector(hist); +} + +QVector Widget::getHist_BLUE() const +{ + return blueBackColor; +} + +void Widget::setHist_GRAY(const QVector &hist) +{ + grayBackColor = QVector(hist); +} + +QVector Widget::getHist_GRAY() const +{ + return grayBackColor; +} + +void Widget::drawCoordinate(QPainter &painter) +{ + painter.setBrush(QColor(79,79,79)); + painter.drawRect(0, 0, 260, 260); + painter.drawLine(-2000,0,2000,0); + painter.drawLine(0,1500,0,-1500); +} + +void Widget::drawBackgroudColor(QPainter &painter,QVector &curCol) +{ + painter.setPen(QPen(color,1)); + painter.setBrush(color); + int max = 0; + for(int i = 0; i < curCol.size(); i++) + { + if(curCol.at(i) > max) + { + max = curCol.at(i); + } + } + for(int i = 0; i < curCol.size(); i++) + { + painter.drawRect(i, 0, 1, curCol.at(i)*255/max); + } + +} + +void Widget::drawBackColorBySlc(QPainter &painter) +{ + switch(selectCol){ + case RGB: + drawBackgroudColor(painter,rgbBackColor); + break; + case GREEN: + drawBackgroudColor(painter,greenBackColor); + break; + case BLUE: + drawBackgroudColor(painter,blueBackColor); + break; + case RED: + drawBackgroudColor(painter,redBackColor); + break; + case GRAY: + drawBackgroudColor(painter,grayBackColor); + break; + } +} + +void Widget::drawCoorScale(QPainter &painter) +{ + painter.setPen(QPen(Qt::gray,1)); + for(int i = 0; i < 260 ; i+=50) + { + if(i%50 == 0 && i >=50) + { + QVector dashes; + qreal space = 3; + dashes << 5 << space << 5 < &plst, const int& col) +{ + double **a; + int len = plst.size(); + a = new double *[len]; + for(int i = 0; i < len; i++){ + a[i] = new double[len+1]; + } + /*******通过pointLst的所有点给二维数组赋值生成行列式*******/ + for(int i = 0; i < len; i++){ + for(int j = 0;j < len + 1; j++){ + if(j < len) + a[i][j] = caculateAllMi(plst.at(i).x(),len-j-1); + if(j == len) + a[i][j] = plst.at(i).y(); + } + } + + /*******调用高斯消元法计算曲线方程的系数值********/ + GaoSiXY gaoSi; + double *result = new double[len] ; + gaoSi.solve(a,len,result); + + /********保存曲线方程 x 的系数(a,b,c,d....)********/ + QList xiNum; + for(int i = 0; i < len; i++){ + xiNum.append(*(result+i)); + } + + linePoint.clear(); + linePoints.clear(); + for(int i = 0; i < 256; i++){ + int x = i; + double yVal = 0; + for(int j = 0; j < len; j++){ + yVal += xiNum.at(j)*caculateAllMi(x,len-j-1); + } + int y = (int)yVal; + if(y > 255) y = 255; + if(y < 0) y = 0; + if(x < plst.at(0).x()) y = plst.at(0).y(); + if(x > plst.at(1).x()) y = plst.at(1).y(); + allLinePoints[x] = y; + linePoints.append(y); + linePoint.append(QPoint(x,y)); + } + + + if(col == RED){ + redALLPoint.clear(); + for(int i = 0; i < linePoint.size(); i++) + redALLPoint.append(linePoint.at(i).y()); + } + if(col == GREEN){ + greenALLPoint.clear(); + for(int i = 0; i < linePoint.size(); i++) + greenALLPoint.append(linePoint.at(i).y()); + } + if(col == BLUE){ + blueALLPoint.clear(); + for(int i = 0; i < linePoint.size(); i++) + blueALLPoint.append(linePoint.at(i).y()); + } + if(col == GRAY){ + grayALLPoint.clear(); + for(int i = 0; i < linePoint.size(); i++) + grayALLPoint.append(linePoint.at(i).y()); + } + if(col == RGB){ + rgbALLPoint.clear(); + for(int i = 0; i < linePoint.size(); i++) + { + rgbALLPoint.append(linePoint.at(i).y()); + } + } + + + for(int i = 0;i < len; i++){ + delete[] a[i]; + } + delete []a; +} + +void Widget::drawAllPoint(QPainter &painter) +{ + if(pointLst.size() > 0) + { + painter.setPen(QPen(Qt::white,1)); + painter.setBrush(Qt::white); + for(int i = 0; i < pointLst.size(); i++){ + painter.drawEllipse(pointLst.at(i),3,3); + } + if(dragPoint >= 0){ + painter.setPen(QPen(QColor(0, 245, 255),2)); + painter.drawEllipse(pointLst[dragPoint],4,4); + } + } + + if(selectCol == GREEN){ + greenLine.clear(); + greenLine = QList(pointLst); + } + else if(selectCol == RED){ + redLine.clear(); + redLine = QList(pointLst); + }else if(selectCol == BLUE){ + blueLine.clear(); + blueLine = QList(pointLst); + }else if(selectCol == RGB){ + rgbLine.clear(); + rgbLine = QList(pointLst); + }else if(selectCol == GRAY){ + grayLine.clear(); + grayLine = QList(pointLst); + } +} + +void Widget::drawCurveByColor(QPainter &painter) +{ + qDebug() << selectCol; + switch (selectCol) { + case RGB: + painter.setPen(QPen(Qt::white,1)); + drawLineFromPoint(rgbLine, RGB); + drawLineByVector(painter,rgbALLPoint); + if(redLine.size()>2 || redLine.at(0)!= QPoint(0,0) || redLine.at(1)!= QPoint(255,255)){ + painter.setPen(QPen(Qt::red,1)); + drawLineFromPoint(redLine,RED); + drawLineByVector(painter,redALLPoint); + } + if(blueLine.size()>2 || blueLine.at(0)!= QPoint(0,0) || blueLine.at(1)!= QPoint(255,255)){ + painter.setPen(QPen(Qt::blue,1)); + drawLineFromPoint(blueLine, BLUE); + drawLineByVector(painter,blueALLPoint); + } + if(greenLine.size()>2 || greenLine.at(0)!= QPoint(0,0) || greenLine.at(1)!= QPoint(255,255)){ + painter.setPen(QPen(Qt::green,1)); + drawLineFromPoint(greenLine, BLUE); + drawLineByVector(painter,greenALLPoint); + } + break; + case RED: + painter.setPen(QPen(Qt::red,1)); + drawLineFromPoint(redLine,RED); + drawLineByVector(painter,redALLPoint); + break; + case BLUE: + painter.setPen(QPen(Qt::blue,1)); + drawLineFromPoint(blueLine, BLUE); + drawLineByVector(painter,blueALLPoint); + break; + case GREEN: + painter.setPen(QPen(Qt::green,1)); + drawLineFromPoint(greenLine, GREEN); + drawLineByVector(painter,greenALLPoint); + break; + case GRAY: + painter.setPen(QPen(Qt::white,1)); + drawLineFromPoint(grayLine, GRAY); + drawLineByVector(painter,grayALLPoint); + break; + default: + break; + } + drawLineFromPoint(pointLst, -1); +} + +void Widget::drawLineByVector(QPainter &painter,QVector &pVec) +{ + for(int i = 0; i < pVec.size()-1; i++){ + painter.drawLine(QPoint(i,pVec.at(i)),QPoint(i+1,pVec.at(i+1))); + } + update(); +} + +int Widget::caculateAllMi(int num, int n) +{ + int val = 1; + if(n == 0) return 1; + for(int i = 0; i < n; i++){ + val *= num; + } + return val; +} + +void Widget::getCurLineLUT(uchar *table, size_t length) +{ + for(size_t i = 0; i < length; i++) + { + table[i] = allLinePoints[i]; + } +} + +QVector Widget::getCurLinePntVec() +{ + return linePoints; +} + +void Widget::updateCurLinePnt(const int& colType) +{ + dragPoint = -1; + selectCol = colType; + if(selectCol == GREEN){ + color = QColor(202, 255, 112); + pointLst.clear(); + pointLst = QList(greenLine); + ui->widget_2->setStyleSheet("QWidget{background-color:qlineargradient(" + "spread:pad, x1:0, y1:0, x2:1, y2:0, " + "stop:0 rgba(0, 0, 0, 255), stop:1 rgba(0, 255, 0, 255))}"); + ui->widget->setStyleSheet("QWidget{background-color:qlineargradient(" + "spread:pad, x1:0, y1:1, x2:0, y2:0, " + "stop:0 rgba(0, 0, 0, 255), stop:1 rgba(0, 255, 0, 255))}"); + }else if(selectCol == BLUE){ + color = QColor(131, 111, 255); + pointLst.clear(); + pointLst = QList(blueLine); + ui->widget_2->setStyleSheet("QWidget{background-color:qlineargradient(" + "spread:pad, x1:0, y1:0, x2:1, y2:0, " + "stop:0 rgba(0, 0, 0, 255), stop:1 rgba(0, 0, 255, 255))}"); + ui->widget->setStyleSheet("QWidget{background-color:qlineargradient(" + "spread:pad, x1:0, y1:1, x2:0, y2:0, " + "stop:0 rgba(0, 0, 0, 255), stop:1 rgba(0, 0, 255, 255))}"); + }else if(selectCol == RED){ + color = QColor(255, 160, 122); + pointLst.clear(); + pointLst = QList(redLine); + ui->widget_2->setStyleSheet("QWidget{background-color:qlineargradient(" + "spread:pad, x1:0, y1:0, x2:1, y2:0, " + "stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 0, 0, 255))}"); + ui->widget->setStyleSheet("QWidget{background-color:qlineargradient(" + "spread:pad, x1:0, y1:1, x2:0, y2:0, " + "stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 0, 0, 255))}"); + }else if(selectCol == GRAY){ + color = Qt::gray; + pointLst.clear(); + pointLst = QList(grayLine); + ui->widget_2->setStyleSheet("QWidget{background-color:qlineargradient(" + "spread:pad, x1:0, y1:0, x2:1, y2:0, " + "stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 255, 255, 255))}"); + ui->widget->setStyleSheet("QWidget{background-color:qlineargradient(" + "spread:pad, x1:0, y1:1, x2:0, y2:0, " + "stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 255, 255, 255))}"); + }else if(selectCol == RGB){ + color = Qt::gray; + pointLst.clear(); + pointLst = QList(rgbLine); + ui->widget_2->setStyleSheet("QWidget{background-color:qlineargradient(" + "spread:pad, x1:0, y1:0, x2:1, y2:0, " + "stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 255, 255, 255))}"); + ui->widget->setStyleSheet("QWidget{background-color:qlineargradient(" + "spread:pad, x1:0, y1:1, x2:0, y2:0, " + "stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 255, 255, 255))}"); + } + update(); +} + +void Widget::setXCoorVal(const int &xVal) +{ + if(dragPoint >= 0){ + int x = xVal; + if(pointLst[dragPoint] != pointLst.at(0) && pointLst[dragPoint] != pointLst.at(1)){ + if(pointLst.size() == 3 && x > pointLst.at(0).x() && x < pointLst.at(1).x()) + pointLst[dragPoint].setX(x); + + if(pointLst.size() == 4){ + if(dragPoint == 2){ + if(pointLst[2].x() > pointLst[3].x() && x > pointLst[3].x() && x < pointLst[1].x()) + pointLst[dragPoint].setX(x); + if(pointLst[2].x() < pointLst[3].x() && x < pointLst[3].x() && x > pointLst[0].x()) + pointLst[dragPoint].setX(x); + } + else if(dragPoint == 3){ + if(pointLst[2].x() < pointLst[3].x() && x > pointLst[2].x() && x < pointLst[1].x()) + pointLst[dragPoint].setX(x); + if(pointLst[2].x() > pointLst[3].x() && x < pointLst[2].x() && x > pointLst[0].x()) + pointLst[dragPoint].setX(x); + } + } + } + else if(pointLst[dragPoint] == pointLst.at(0)){ + int min = 999; + for(int i = 1; i < pointLst.size(); i++){ + if(min > pointLst[i].x()) min = pointLst[i].x(); + } + if(x < min) pointLst[dragPoint].setX(x); + } + else if(pointLst[dragPoint] == pointLst.at(1)){ + if(pointLst.size() > 2){ + int max = 0; + for(int i = 2; i < pointLst.size(); i++){ + if(max < pointLst[i].x()) max = pointLst[i].x(); + } + if(x > max) pointLst[dragPoint].setX(x); + } + else if(pointLst.size() <= 2) + if(x > pointLst.at(0).x()) pointLst[dragPoint].setX(x); + } + update(); + } +} + +void Widget::setYCoorVal(const int &yVal) +{ + if(dragPoint >= 0){ + pointLst[dragPoint].setY(yVal); + update(); + } +} + +void Widget::initSelectColLine(const int& colType) +{ + pointLst.clear(); + pointLst.append(QPoint(0,0)); + pointLst.append(QPoint(255,255)); + switch(colType){ + case RED: + redLine.clear(); + redLine.append(QPoint(0,0)); + redLine.append(QPoint(255,255)); + break; + case BLUE: + blueLine.clear(); + blueLine.append(QPoint(0,0)); + blueLine.append(QPoint(255,255)); + break; + case GREEN: + greenLine.clear(); + greenLine.append(QPoint(0,0)); + greenLine.append(QPoint(255,255)); + break; + case GRAY: + grayLine.clear(); + grayLine.append(QPoint(0,0)); + grayLine.append(QPoint(255,255)); + break; + case RGB: + initAllLstPnt(); + break; + } + dragPoint = -1; + leftMouseMv = false; + newPoint = false; + clickLine = false; + setMouseTracking(true); + qDebug() << "init"; + updateCurLinePnt(colType); +} + +void Widget::SetAllLinePnt(QVector &all) +{ + allLinePntSet = QVector(all); +} + diff --git a/modules/saneui/widget.h b/modules/saneui/widget.h new file mode 100644 index 00000000..0ff62115 --- /dev/null +++ b/modules/saneui/widget.h @@ -0,0 +1,132 @@ +#ifndef WIDGET_H +#define WIDGET_H + +#include +#include +//#include "colorlinesetdef.h" + +namespace Ui { +class Widget; +} +// +//enum COLOR_TPYE +//{ +// RGB, +// GRAY, +// RED, +// BLUE, +// GREEN +//}; + +class Widget : public QWidget +{ + Q_OBJECT + +public: + explicit Widget(QWidget *parent = nullptr); + ~Widget(); + void initAllLstPnt(); //初始化所有颜色曲线 + void setLstPnt_RGB(const QList& plst); //设置生成RGB曲线的关键点(<=4) + QList getLstPnt_RGB()const; //获取生成RGB曲线的关键点 + void setLstPnt_RED(const QList& plst); + QList getLstPnt_RED()const; + void setLstPnt_BLUE(const QList& plst); + QList getLstPnt_BLUE()const; + void setLstPnt_GREEN(const QList& plst); + QList getLstPnt_GREEN()const; + void setLstPnt_GRAY(const QList& plst); + QList getLstPnt_GRAY()const; + + QVector getRgbALLPoint(); + QList getRgbKeyPoint()const; + void setRgbKeyPoint(const QList& pVec); + QVector getRedALLPoint(); + QList getRedKeyPoint()const; + void setRedKeyPoint(const QList& pVec); + QVector getBlueALLPoint(); + QList getBlueKeyPoint()const; + void setBlueKeyPoint(const QList& pVec); + QVector getGreenALLPoint(); + QList getGreenKeyPoint()const; + void setGreenKeyPoint(const QList& pVec); + QVector getGrayALLPoint(); + QList getGrayKeyPoint()const; + void setGrayKeyPoint(const QList& pVec); + + void setHist_RGB(const QVector& hist);//设置RGB的背景直方图 + QVector getHist_RGB()const;//获取RGB的背景直方图 + void setHist_RED(const QVector& hist); + QVector getHist_RED()const; + void setHist_BLUE(const QVector& hist); + QVector getHist_BLUE()const; + void setHist_GREEN(const QVector& hist); + QVector getHist_GREEN()const; + void setHist_GRAY(const QVector& hist); + QVector getHist_GRAY()const; + + void getCurLineLUT(uchar* table, size_t length = 256);//获取当前曲线上的所有点并存入table + QVector getCurLinePntVec();//获取当前曲线上的所有点 + void setXCoorVal(const int &xVal);//设置被选中的点的X坐标 + void setYCoorVal(const int &yVal);//设置被选中的点的Y坐标 + void updateCurLinePnt(const int& colType);//根据当前所选颜色(colType)重绘界面 + void initSelectColLine(const int& colType);//初始化当前所选颜色(colType)界面的曲线 + void SetAllLinePnt(QVector& all);//设置自定义曲线的所有点 + +signals: + void dragPointChecked(bool);//曲线上的点被选中的信号 + void mouseLeaveSig();//鼠标离开控件的信号 + void mouseCoordSig(QPoint pos);//鼠标的坐标信号 + void lineChangeSig(); + +private: + void initInterface();//初始化界面 + void paintEvent(QPaintEvent *); + void mousePressEvent(QMouseEvent*); + void mouseMoveEvent(QMouseEvent*); + void mouseReleaseEvent(QMouseEvent*); + void enterEvent(QEvent*); + void leaveEvent(QEvent*); + void drawCoordinate(QPainter&);//画直角坐标 + void drawBackgroudColor(QPainter&,QVector&);//画背景直方图 + void drawBackColorBySlc(QPainter&);//画不同的背景直方图 + void drawCoorScale(QPainter&);//画虚线刻度 + void drawLineFromPoint(QList &plst, const int &col);//根据多点求出曲线方程,并画出曲线 + void drawAllPoint(QPainter&);//画出生成曲线的关键点 + void drawCurveByColor(QPainter&);//画不同的颜色曲线 + void drawLineByVector(QPainter&,QVector&);//将数组的所有点连接绘制曲线 + int caculateAllMi(int num,int n);//计算num的n次方的值 + +private: + Ui::Widget *ui; + QVector rgbBackColor; + QVector redBackColor; + QVector blueBackColor; + QVector greenBackColor; + QVector grayBackColor; + QVector rgbALLPoint; + QVector redALLPoint; + QVector blueALLPoint; + QVector greenALLPoint; + QVector grayALLPoint; + QVector allLinePntSet; + QVector linePoints; + + //QList points; + QList pointLst; + QList linePoint; + QList greenLine; + QList redLine; + QList blueLine; + QList rgbLine; + QList grayLine; + QColor color; + + unsigned char allLinePoints[256]; + bool leftMouseMv; + bool newPoint; + bool clickLine; + int dragPoint; + int selectCol; +}; + +#endif // WIDGET_H diff --git a/modules/saneui/widget.ui b/modules/saneui/widget.ui new file mode 100644 index 00000000..aaf5af1c --- /dev/null +++ b/modules/saneui/widget.ui @@ -0,0 +1,91 @@ + + + Widget + + + + 0 + 0 + 556 + 484 + + + + Widget + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 0 + + + + true + + + Qt::WheelFocus + + + QWidget{background-color:qlineargradient(spread:pad, x1:0, y1:1, x2:0, y2:0, stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 255, 255, 255))} + + + + + + + + 0 + 20 + + + + true + + + Qt::NoFocus + + + + + + + + 0 + 0 + + + + QWidget{background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(0, 0, 0, 255), stop:1 rgba(255, 255, 255, 255))} + + + + + + + + +