增加TwainUI工程
This commit is contained in:
parent
7d92512f9f
commit
45574a4418
|
@ -6,6 +6,7 @@ SUBDIRS += \
|
||||||
HGImgProc \
|
HGImgProc \
|
||||||
HGSaneUI \
|
HGSaneUI \
|
||||||
HGSaneUser \
|
HGSaneUser \
|
||||||
|
HGTwainUI \
|
||||||
HGTwainUser \
|
HGTwainUser \
|
||||||
HGVersion \
|
HGVersion \
|
||||||
HGScannerLib \
|
HGScannerLib \
|
||||||
|
@ -31,6 +32,9 @@ HGSaneUser.depends = \
|
||||||
HGBase \
|
HGBase \
|
||||||
HGSaneUI
|
HGSaneUI
|
||||||
|
|
||||||
|
HGTwainUI.depends = \
|
||||||
|
HGBase
|
||||||
|
|
||||||
HGTwainUser.depends = \
|
HGTwainUser.depends = \
|
||||||
HGBase \
|
HGBase \
|
||||||
HGSaneUI
|
HGSaneUI
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
LIBRARY
|
||||||
|
|
||||||
|
EXPORTS
|
||||||
|
|
||||||
|
choose_scanner
|
||||||
|
apply_current_config
|
||||||
|
twain_ui_free
|
||||||
|
show_setting_ui
|
||||||
|
show_progress_ui
|
|
@ -0,0 +1,222 @@
|
||||||
|
QT += core gui
|
||||||
|
|
||||||
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets gui-private
|
||||||
|
|
||||||
|
TEMPLATE = lib
|
||||||
|
DEFINES += UNTITLED_LIBRARY
|
||||||
|
|
||||||
|
CONFIG += c++11
|
||||||
|
CONFIG += dll
|
||||||
|
|
||||||
|
# The following define makes your compiler emit warnings if you use
|
||||||
|
# any Qt feature that has been marked deprecated (the exact warnings
|
||||||
|
# depend on your compiler). Please consult the documentation of the
|
||||||
|
# deprecated API in order to know how to port your code away from it.
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS
|
||||||
|
DEFINES += QT_NO_VERSION_TAGGING
|
||||||
|
|
||||||
|
# You can also make your code fail to compile if it uses deprecated APIs.
|
||||||
|
# In order to do so, uncomment the following line.
|
||||||
|
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||||
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||||
|
|
||||||
|
include($$PWD/../HGOEM.pri)
|
||||||
|
|
||||||
|
CONFIG(debug, debug|release) {
|
||||||
|
MY_CONFIGURE = Debug
|
||||||
|
}
|
||||||
|
CONFIG(release, debug|release) {
|
||||||
|
MY_CONFIGURE = Release
|
||||||
|
}
|
||||||
|
|
||||||
|
win32 {
|
||||||
|
|
||||||
|
SOURCES += ../../../modules/twainui/qmfcapp.cpp
|
||||||
|
SOURCES += ../../../modules/twainui/qwinhost.cpp
|
||||||
|
SOURCES += ../../../modules/twainui/qwinwidget.cpp
|
||||||
|
SOURCES += ../../../modules/twainui/twainui.cpp
|
||||||
|
SOURCES += ../../../modules/twainui/hg_settingdialog.cpp
|
||||||
|
|
||||||
|
HEADERS += ../../../modules/twainui/qmfcapp.hpp
|
||||||
|
HEADERS += ../../../modules/twainui/qwinhost.hpp
|
||||||
|
HEADERS += ../../../modules/twainui/qwinwidget.hpp
|
||||||
|
HEADERS += ../../../modules/twainui/twainui.h
|
||||||
|
HEADERS += ../../../modules/twainui/hg_settingdialog.h
|
||||||
|
|
||||||
|
MY_OS = windows
|
||||||
|
TARGET = $${OEM_PREFIX}TwainUI
|
||||||
|
|
||||||
|
contains(QT_ARCH, i386) {
|
||||||
|
MY_ARCH = x86
|
||||||
|
}
|
||||||
|
contains(QT_ARCH, x86_64) {
|
||||||
|
MY_ARCH = x64
|
||||||
|
}
|
||||||
|
|
||||||
|
CONFIG(release, debug|release) {
|
||||||
|
QMAKE_LFLAGS_RELEASE += /MAP
|
||||||
|
QMAKE_CFLAGS_RELEASE += /Zi
|
||||||
|
QMAKE_LFLAGS_RELEASE += /debug /opt:ref
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF_FILE = HGTwainUI.def
|
||||||
|
LIBS += -lgdi32 -lgdiplus -ldbghelp -luser32
|
||||||
|
LIBS += -L$$PWD/../../build/$${MY_OS}/$${OEM_NAME}/$${MY_ARCH}/$${MY_CONFIGURE} -l$${OEM_PREFIX}Base
|
||||||
|
LIBS += -L$$PWD/../../../../sdk/lib/win/$${MY_ARCH}/OEM/$${OEM_NAME} -llang
|
||||||
|
}
|
||||||
|
|
||||||
|
unix {
|
||||||
|
|
||||||
|
DISTRIBUTION = $$system(cat /etc/issue | cut -d\' \' -f1)
|
||||||
|
contains(DISTRIBUTION, UnionTech) {
|
||||||
|
MY_OS = uos
|
||||||
|
} else {
|
||||||
|
MY_OS = kylin
|
||||||
|
}
|
||||||
|
TARGET = $${OEM_PREFIX2}TwainUI
|
||||||
|
|
||||||
|
contains(QT_ARCH, x86_64) {
|
||||||
|
MY_ARCH = amd64
|
||||||
|
MY_ARCH2 = x86_64
|
||||||
|
}
|
||||||
|
contains(QT_ARCH, arm64) {
|
||||||
|
MY_ARCH = aarch64
|
||||||
|
MY_ARCH2 = aarch64
|
||||||
|
}
|
||||||
|
contains(QT_ARCH, mips64) {
|
||||||
|
MY_ARCH = mips64
|
||||||
|
MY_ARCH2 = mips64
|
||||||
|
}
|
||||||
|
contains(QT_ARCH, loongarch64) {
|
||||||
|
MY_ARCH = loongarch64
|
||||||
|
MY_ARCH2 = loongarch64
|
||||||
|
}
|
||||||
|
|
||||||
|
CONFIG += unversioned_libname unversioned_soname
|
||||||
|
QMAKE_CXXFLAGS += -fvisibility=hidden
|
||||||
|
QMAKE_LFLAGS += -static-libstdc++ -static-libgcc
|
||||||
|
QMAKE_LFLAGS += -Wl,-rpath,\'\$\$ORIGIN\' -Wl,--exclude-libs,ALL
|
||||||
|
QMAKE_LFLAGS += -z defs -B direct
|
||||||
|
|
||||||
|
LIBS += -lpthread -ldl
|
||||||
|
LIBS += -L$$PWD/../../build/$${MY_OS}/$${OEM_NAME}/$${MY_ARCH}/$${MY_CONFIGURE} -l$${OEM_PREFIX2}Base
|
||||||
|
LIBS += -L$$PWD/../../../../release/$${MY_OS}/$${MY_ARCH2} -llang
|
||||||
|
}
|
||||||
|
|
||||||
|
INCLUDEPATH += $$PWD/../../../modules
|
||||||
|
INCLUDEPATH += $$PWD/../../../utility
|
||||||
|
INCLUDEPATH += $$PWD/../../../modules/saneui
|
||||||
|
INCLUDEPATH += $$PWD/../../../modules/twainui
|
||||||
|
INCLUDEPATH += $$PWD/../../../../sdk/include
|
||||||
|
|
||||||
|
DESTDIR = $$PWD/../../build/$${MY_OS}/$${OEM_NAME}/$${MY_ARCH}/$${MY_CONFIGURE}
|
||||||
|
UI_DIR = $$PWD/../../temp/$${MY_OS}/$${OEM_NAME}/$${MY_ARCH}/$${MY_CONFIGURE}/$${TARGET}
|
||||||
|
MOC_DIR = $$PWD/../../temp/$${MY_OS}/$${OEM_NAME}/$${MY_ARCH}/$${MY_CONFIGURE}/$${TARGET}
|
||||||
|
OBJECTS_DIR = $$PWD/../../temp/$${MY_OS}/$${OEM_NAME}/$${MY_ARCH}/$${MY_CONFIGURE}/$${TARGET}
|
||||||
|
RCC_DIR = $$PWD/../../temp/$${MY_OS}/$${OEM_NAME}/$${MY_ARCH}/$${MY_CONFIGURE}/$${TARGET}
|
||||||
|
|
||||||
|
message(MY_OS: $$MY_OS)
|
||||||
|
message(MY_ARCH: $$MY_ARCH)
|
||||||
|
message(OEM_PREFIX: $$OEM_PREFIX)
|
||||||
|
message(OEM_PREFIX2: $$OEM_PREFIX2)
|
||||||
|
message(OEM_NAME: $$OEM_NAME)
|
||||||
|
message(MY_CONFIGURE: $$MY_CONFIGURE)
|
||||||
|
message(TARGET: $$TARGET)
|
||||||
|
message(DESTDIR: $$DESTDIR)
|
||||||
|
message(UI_DIR: $$UI_DIR)
|
||||||
|
message(MOC_DIR: $$MOC_DIR)
|
||||||
|
message(OBJECTS_DIR: $$OBJECTS_DIR)
|
||||||
|
message(RCC_DIR: $$RCC_DIR)
|
||||||
|
|
||||||
|
win32 {
|
||||||
|
|
||||||
|
CONFIG(release, debug|release) {
|
||||||
|
DESTLIB_PATH = $${PWD}/../../../../sdk/lib/win/$${MY_ARCH}/$${MY_CONFIGURE}/
|
||||||
|
DESTLIB_PATH = $$replace(DESTLIB_PATH, /, \\)
|
||||||
|
message(DESTLIB_PATH: $$DESTLIB_PATH)
|
||||||
|
DESTDLL_PATH = $${PWD}/../../../../release/win/$${MY_ARCH}/$${MY_CONFIGURE}/
|
||||||
|
DESTDLL_PATH = $$replace(DESTDLL_PATH, /, \\)
|
||||||
|
message(DESTDLL_PATH: $$DESTDLL_PATH)
|
||||||
|
DESTHEADER_PATH = $${PWD}/../../../../sdk/include/twainui/
|
||||||
|
DESTHEADER_PATH = $$replace(DESTHEADER_PATH, /, \\)
|
||||||
|
message(DESTHEADER_PATH: $$DESTHEADER_PATH)
|
||||||
|
|
||||||
|
SRCLIB_FILE = $${DESTDIR}/$${TARGET}.lib
|
||||||
|
SRCLIB_FILE = $$replace(SRCLIB_FILE, /, \\)
|
||||||
|
message(SRCLIB_FILE: $$SRCLIB_FILE)
|
||||||
|
SRCDLL_FILE = $${DESTDIR}/$${TARGET}.dll
|
||||||
|
SRCDLL_FILE = $$replace(SRCDLL_FILE, /, \\)
|
||||||
|
message(SRCDLL_FILE: $$SRCDLL_FILE)
|
||||||
|
SRCHEADER_FILE = $${PWD}/../../../modules/twainui/HGTwainUI.h
|
||||||
|
SRCHEADER_FILE = $$replace(SRCHEADER_FILE, /, \\)
|
||||||
|
message(SRCHEADER_FILE: $$SRCHEADER_FILE)
|
||||||
|
SRCPDB_FILE = $${DESTDIR}/$${TARGET}.pdb
|
||||||
|
SRCPDB_FILE = $$replace(SRCPDB_FILE, /, \\)
|
||||||
|
message(SRCPDB_FILE: $$SRCPDB_FILE)
|
||||||
|
|
||||||
|
QMAKE_POST_LINK += xcopy /y $$SRCLIB_FILE $$DESTLIB_PATH && xcopy /y $$SRCDLL_FILE $$DESTDLL_PATH \
|
||||||
|
&& xcopy /y $$SRCHEADER_FILE $$DESTHEADER_PATH && xcopy /y $$SRCPDB_FILE $$DESTDLL_PATH
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unix {
|
||||||
|
|
||||||
|
CONFIG(release, debug|release) {
|
||||||
|
DESTDLL_PATH = $$PWD/../../../../release/$${MY_OS}/$${MY_ARCH2}/
|
||||||
|
message(DESTDLL_PATH: $$DESTDLL_PATH)
|
||||||
|
DESTHEADER_PATH = $${PWD}/../../../../sdk/include/twainui/
|
||||||
|
message(DESTHEADER_PATH: $$DESTHEADER_PATH)
|
||||||
|
|
||||||
|
SRCDLL_FILE = $${DESTDIR}/lib$${TARGET}.so
|
||||||
|
message(SRCDLL_FILE: $$SRCDLL_FILE)
|
||||||
|
SRCHEADER_FILE = $${PWD}/../../../modules/twainui/*.h
|
||||||
|
message(SRCHEADER_FILE: $$SRCHEADER_FILE)
|
||||||
|
|
||||||
|
QMAKE_POST_LINK += cp $$SRCDLL_FILE $$DESTDLL_PATH && cp $$SRCHEADER_FILE $$DESTHEADER_PATH
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
../../../modules/twainui/cfg/cJSON.c \
|
||||||
|
../../../modules/twainui/cfg/gb_json.cpp \
|
||||||
|
../../../modules/twainui/cutdialog.cpp \
|
||||||
|
../../../modules/twainui/cutpapertool.cpp \
|
||||||
|
../../../modules/twainui/device_menu.cpp \
|
||||||
|
../../../modules/twainui/dialog_input.cpp \
|
||||||
|
../../../modules/twainui/dllmain.cpp \
|
||||||
|
../../../modules/twainui/gaosixy.cpp \
|
||||||
|
../../../modules/twainui/setpicclrtool.cpp \
|
||||||
|
../../../utility/HGString.cpp \
|
||||||
|
../../../modules/twainui/widget.cpp \
|
||||||
|
../../../modules/twainui/dialog_progress_ui.cpp \
|
||||||
|
../../../modules/twainui/dialog_device_select.cpp
|
||||||
|
HEADERS += \
|
||||||
|
../../../modules/twainui/cfg/cJSON.h \
|
||||||
|
../../../modules/twainui/cfg/gb_json.h \
|
||||||
|
../../../modules/twainui/cutdialog.h \
|
||||||
|
../../../modules/twainui/cutpapertool.h \
|
||||||
|
../../../modules/twainui/device_menu.h \
|
||||||
|
../../../modules/twainui/dialog_input.h \
|
||||||
|
../../../modules/twainui/gaosixy.h \
|
||||||
|
../../../modules/twainui/setpicclrtool.h \
|
||||||
|
../../../utility/HGString.h \
|
||||||
|
../../../modules/twainui/widget.h \
|
||||||
|
../../../modules/twainui/dialog_progress_ui.h \
|
||||||
|
../../../modules/twainui/dialog_device_select.h
|
||||||
|
|
||||||
|
FORMS += \
|
||||||
|
../../../modules/twainui/cutdialog.ui \
|
||||||
|
../../../modules/twainui/cutpapertool.ui \
|
||||||
|
../../../modules/twainui/dialog_input.ui \
|
||||||
|
../../../modules/twainui/setpicclrtool.ui \
|
||||||
|
../../../modules/twainui/widget.ui \
|
||||||
|
../../../modules/twainui/dialog_progress_ui.ui \
|
||||||
|
../../../modules/twainui/dialog_device_select.ui
|
||||||
|
|
||||||
|
RESOURCES += \
|
||||||
|
../../../modules/twainui/TwainUI_resource.qrc
|
||||||
|
|
||||||
|
TRANSLATIONS += \
|
||||||
|
../../../modules/twainui/TwainUI_zh_CN.ts \
|
||||||
|
../../../modules/twainui/TwainUI_zh_EN.ts \
|
||||||
|
../../../modules/twainui/qt_zh_CN.ts
|
|
@ -0,0 +1,7 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="/translation">
|
||||||
|
<file>TwainUI_zh_CN.qm</file>
|
||||||
|
<file>TwainUI_zh_EN.qm</file>
|
||||||
|
<file>qt_zh_CN.qm</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -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 <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#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;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
|
||||||
|
cJSON_free(entries);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compose the output array. */
|
||||||
|
*out='[';
|
||||||
|
ptr=out+1;*ptr=0;
|
||||||
|
for (i=0;i<numentries;i++)
|
||||||
|
{
|
||||||
|
tmplen=strlen(entries[i]);memcpy(ptr,entries[i],tmplen);ptr+=tmplen;
|
||||||
|
if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
|
||||||
|
cJSON_free(entries[i]);
|
||||||
|
}
|
||||||
|
cJSON_free(entries);
|
||||||
|
*ptr++=']';*ptr++=0;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Build an object from the text. */
|
||||||
|
static const char *parse_object(cJSON *item,const char *value)
|
||||||
|
{
|
||||||
|
cJSON *child;
|
||||||
|
if (*value!='{') {ep=value;return 0;} /* not an object! */
|
||||||
|
|
||||||
|
item->type=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;i<depth-1;i++) *ptr++='\t';}
|
||||||
|
*ptr++='}';*ptr++=0;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
if (p)
|
||||||
|
{
|
||||||
|
/* Compose the output: */
|
||||||
|
i=p->offset;
|
||||||
|
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;j<depth;j++) *ptr++='\t';
|
||||||
|
p->offset+=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;i<depth-1;i++) *ptr++='\t';
|
||||||
|
*ptr++='}';*ptr=0;
|
||||||
|
out=(p->buffer)+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;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
|
||||||
|
cJSON_free(names);cJSON_free(entries);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compose the output: */
|
||||||
|
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
|
||||||
|
for (i=0;i<numentries;i++)
|
||||||
|
{
|
||||||
|
if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
|
||||||
|
tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen;
|
||||||
|
*ptr++=':';if (fmt) *ptr++='\t';
|
||||||
|
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
|
||||||
|
if (i!=numentries-1) *ptr++=',';
|
||||||
|
if (fmt) *ptr++='\n';*ptr=0;
|
||||||
|
cJSON_free(names[i]);cJSON_free(entries[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
cJSON_free(names);cJSON_free(entries);
|
||||||
|
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
|
||||||
|
*ptr++='}';*ptr++=0;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get Array size/item / object item. */
|
||||||
|
int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;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 && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=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 && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=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 && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=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 && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=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. */
|
||||||
|
}
|
|
@ -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 <stdlib.h>
|
||||||
|
|
||||||
|
#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
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,233 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#if defined(WIN32) || defined(_WIN64)
|
||||||
|
#include <Windows.h>
|
||||||
|
#define PATH_SYMBOL "\\"
|
||||||
|
#else
|
||||||
|
#define PATH_SYMBOL "/"
|
||||||
|
#define NULL nullptr
|
||||||
|
#define DWORD_PTR char*
|
||||||
|
#define _countof(a) sizeof(a) / sizeof(a[0])
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "cJSON.h"
|
||||||
|
//#include "../../code_device/hgsane/cJSON.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
namespace gb
|
||||||
|
{
|
||||||
|
class scanner_cfg;
|
||||||
|
class refer
|
||||||
|
{
|
||||||
|
volatile long ref_;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
refer();
|
||||||
|
virtual ~refer();
|
||||||
|
|
||||||
|
public:
|
||||||
|
long add_ref(void);
|
||||||
|
long release(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class json : public refer
|
||||||
|
{
|
||||||
|
cJSON *obj_;
|
||||||
|
cJSON *cur_child_;
|
||||||
|
cJSON walk_head_;
|
||||||
|
bool is_array_;
|
||||||
|
|
||||||
|
cJSON* find_sibling(cJSON* first, const char* name, cJSON*** addr);
|
||||||
|
cJSON* find_child(cJSON *parent, std::vector<std::string>& path, bool create, cJSON*** addr = NULL);
|
||||||
|
cJSON* find(const char* path, bool create = false, cJSON*** addr = NULL);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~json();
|
||||||
|
|
||||||
|
public:
|
||||||
|
json(char* json_txt = 0);
|
||||||
|
|
||||||
|
static std::string to_string(cJSON* root, bool formatted);
|
||||||
|
static std::string get_value_as_string(cJSON* root, bool integer = false);
|
||||||
|
static void free_node_data(cJSON* node);
|
||||||
|
static cJSON* create_element(bool is_array = false);
|
||||||
|
static cJSON* create_element_with_name(const char* name);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool attach_text(char* json_txt);
|
||||||
|
bool attach_cjson(cJSON* cjson);
|
||||||
|
bool create_empty(bool array = false);
|
||||||
|
void clear(void);
|
||||||
|
std::string to_string(bool formatted);
|
||||||
|
|
||||||
|
// can be path: child/value ...
|
||||||
|
bool get_value(const char* key, bool& val);
|
||||||
|
bool get_value(const char* key, int& val);
|
||||||
|
bool get_value(const char* key, double& val);
|
||||||
|
bool get_value(const char* key, std::string& val);
|
||||||
|
bool get_value(const char* key, json*& val); // caller shoud call "delete" to free the returned object !!!
|
||||||
|
bool get_value_as_string(const char* key, std::string& val, bool integer);
|
||||||
|
bool get_as_array(const char* key, std::vector<std::string>& val);
|
||||||
|
|
||||||
|
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<int, std::string> id_name_; // (id, default-val)
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
std::string default_value(const char* name);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~sane_config_schm();
|
||||||
|
|
||||||
|
public:
|
||||||
|
sane_config_schm(scanner_cfg* scanner = nullptr);
|
||||||
|
|
||||||
|
static std::string opt_data_appendix_;
|
||||||
|
static bool hex(unsigned char ch, unsigned char* val);
|
||||||
|
static bool hex_char(const char* data, unsigned char* val);
|
||||||
|
static std::string to_hex_letter(const char* data, size_t bytes);
|
||||||
|
static std::string from_hex_letter(const char* data, size_t bytes);
|
||||||
|
static bool is_option_data(std::string& name); // reset baase option name into 'name' if name was option data, and return true
|
||||||
|
|
||||||
|
public:
|
||||||
|
sane_config_schm* copy(void);
|
||||||
|
bool load_from_file(const char* file);
|
||||||
|
bool load_from_mem(const char* mem, bool in_b64 = true);
|
||||||
|
bool save_to(const char* file);
|
||||||
|
void set_default_value(int sn, const char* name, const char* val, size_t bytes);
|
||||||
|
void copy_default_value(sane_config_schm* from);
|
||||||
|
bool first_config(std::string& name, std::string& val);
|
||||||
|
bool next_config(std::string& name, std::string& val);
|
||||||
|
bool get_config(const char* name, std::string& val);
|
||||||
|
void begin_setting(bool restore = false);
|
||||||
|
void config_changed(const char* name, const char* val, size_t bytes, bool extra = false);
|
||||||
|
void config_changed(int sn, const char* val, size_t bytes, bool extra = false);
|
||||||
|
void remove_config(const char* name);
|
||||||
|
void set_value(const char* name, const char* val, size_t bytes, bool extra = false);
|
||||||
|
bool has_changed(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<CFGSCHM> schemes_;
|
||||||
|
|
||||||
|
static std::string global_name_;
|
||||||
|
static std::string cur_sel_;
|
||||||
|
static std::string default_setting_name_;
|
||||||
|
|
||||||
|
void clear(void);
|
||||||
|
void init_version(void);
|
||||||
|
void init_select(void);
|
||||||
|
void walk_sibling_schemes(cJSON* first);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~scanner_cfg();
|
||||||
|
|
||||||
|
public:
|
||||||
|
scanner_cfg();
|
||||||
|
|
||||||
|
typedef struct _update_func
|
||||||
|
{
|
||||||
|
void(* trans_number)(const char* name, std::string& val, void* param);
|
||||||
|
const char* (* title2name)(const char* title, void* param);
|
||||||
|
std::string discard_msg; // update failed items ...
|
||||||
|
void* func_param;
|
||||||
|
}UDF, *LPUDF;
|
||||||
|
static bool update(const char* file, LPUDF func);
|
||||||
|
|
||||||
|
public:
|
||||||
|
int load_file(const char* file);
|
||||||
|
int load_mem(const char* mem);
|
||||||
|
int save(const char* file = nullptr);
|
||||||
|
|
||||||
|
void get_all_schemes(std::vector<std::string>& schemes); // return all schemes name queue, the first is always be 'Default settings'
|
||||||
|
sane_config_schm* get_scheme(const char* scheme_name = nullptr/*return current scheme if was null*/); // call sane_config_schm::release() if not use anymore
|
||||||
|
std::string get_current_scheme_name(void);
|
||||||
|
bool remove_scheme(const char* scheme_name);
|
||||||
|
void remove_all_schemes(void);
|
||||||
|
bool select_scheme(const char* scheme_name);
|
||||||
|
|
||||||
|
sane_config_schm* copy_scheme(const char* cp_from_name); // for UI setting, call release() if not use anymore
|
||||||
|
bool add_scheme(sane_config_schm* schm, const char* name = nullptr);
|
||||||
|
bool rename_scheme(const char* from, const char* to);
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,464 @@
|
||||||
|
#include "cutdialog.h"
|
||||||
|
#include "ui_cutdialog.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QToolTip>
|
||||||
|
#include <qpainterpath.h>
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
#ifndef CUTDIALOG_H
|
||||||
|
#define CUTDIALOG_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QCursor>
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>cutDialog</class>
|
||||||
|
<widget class="QWidget" name="cutDialog">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>321</width>
|
||||||
|
<height>342</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>2</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="baseSize">
|
||||||
|
<size>
|
||||||
|
<width>2</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="mouseTracking">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>cutDialog</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,219 @@
|
||||||
|
#include "cutpapertool.h"
|
||||||
|
#include "ui_cutpapertool.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QValidator>
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
#ifndef CUTPAPERTOOL_H
|
||||||
|
#define CUTPAPERTOOL_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#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
|
|
@ -0,0 +1,298 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>CutPaperTool</class>
|
||||||
|
<widget class="QWidget" name="CutPaperTool">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>439</width>
|
||||||
|
<height>676</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>自定义扫描区域</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>纸张尺寸:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="paperLab">
|
||||||
|
<property name="text">
|
||||||
|
<string>A4</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="sizeLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>(210*297)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_8">
|
||||||
|
<property name="text">
|
||||||
|
<string>DPI(像素/英寸):</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="dpiLab">
|
||||||
|
<property name="text">
|
||||||
|
<string>200</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_5">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="text">
|
||||||
|
<string>单位:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="comboBox_2">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>毫米(mm)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>英寸(in)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>像素(px)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pbtn_init">
|
||||||
|
<property name="text">
|
||||||
|
<string>初始化选择区域</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QScrollArea" name="scrollArea">
|
||||||
|
<property name="widgetResizable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="scrollAreaWidgetContents_4">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>421</width>
|
||||||
|
<height>430</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="cutDialog" name="widget" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>x:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="startXEdt"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="xLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>mm</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>y:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="startYEdt"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="yLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>mm</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="wLabel_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>w:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="rectWidth"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="wLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>mm</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="text">
|
||||||
|
<string>h:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="rectHeight"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="hLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>mm</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>cutDialog</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header location="global">cutdialog.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -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<std::mutex> lock(mutex_);
|
||||||
|
std::vector<POPMENU>::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<std::mutex> lock(mutex_);
|
||||||
|
std::vector<POPMENU>::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<QString>& dev_names)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> 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<std::mutex> 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<POPMENU>::iterator it = std::find(menus_.begin(), menus_.end(), QString::fromStdString((s.name)));
|
||||||
|
POPMENU pm;
|
||||||
|
std::vector<std::string> schemes;
|
||||||
|
|
||||||
|
if(it == menus_.end())
|
||||||
|
pm.menu = addMenu(QString::fromStdString(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);
|
||||||
|
}
|
|
@ -0,0 +1,494 @@
|
||||||
|
#ifndef DEVICE_MENU_H
|
||||||
|
#define DEVICE_MENU_H
|
||||||
|
|
||||||
|
#include <QMenu>
|
||||||
|
#include <mutex>
|
||||||
|
#include "sane/sane_ex.h"
|
||||||
|
#include "sane/sane_option_definitions.h"
|
||||||
|
#include "../../../sdk/include/huagao/hgscanner_error.h"
|
||||||
|
|
||||||
|
#include "cfg/gb_json.h"
|
||||||
|
#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<SCANNER> que_;
|
||||||
|
std::string root_dir_;
|
||||||
|
std::string opened_scanner_;
|
||||||
|
std::string applied_scheme_;
|
||||||
|
SANE_Handle handle_;
|
||||||
|
|
||||||
|
|
||||||
|
static void trans_number(const char* name, std::string& val, void* param)
|
||||||
|
{
|
||||||
|
if (strcmp(name, "tl-x") == 0
|
||||||
|
|| strcmp(name, "br-x") == 0
|
||||||
|
|| strcmp(name, "tl-y") == 0
|
||||||
|
|| strcmp(name, "br-y") == 0
|
||||||
|
|| strcmp(name, "gamma") == 0
|
||||||
|
|| strcmp(name, "search-hole-range-l") == 0
|
||||||
|
|| strcmp(name, "search-hole-range-r") == 0
|
||||||
|
|| strcmp(name, "search-hole-range-t") == 0
|
||||||
|
|| strcmp(name, "search-hole-range-b") == 0
|
||||||
|
|| strcmp(name, "feed-strength-value") == 0
|
||||||
|
)
|
||||||
|
{
|
||||||
|
float v = atof(val.c_str());
|
||||||
|
SANE_Fixed f = SANE_FIX(v);
|
||||||
|
|
||||||
|
val = std::string((char*)&f, sizeof(f));
|
||||||
|
}
|
||||||
|
else if (strcmp(name, "binary-threshold") == 0
|
||||||
|
|| strcmp(name, "bkg-color-range") == 0
|
||||||
|
|| strcmp(name, "noise-size") == 0
|
||||||
|
|| strcmp(name, "blank-sensitivity") == 0
|
||||||
|
|| strcmp(name, "resolution") == 0
|
||||||
|
|| strcmp(name, "brightness") == 0
|
||||||
|
|| strcmp(name, "contrast") == 0
|
||||||
|
|| strcmp(name, "threshold") == 0
|
||||||
|
|| strcmp(name, "anti-noise-level") == 0
|
||||||
|
|| strcmp(name, "margin") == 0
|
||||||
|
|| strcmp(name, "scan-count") == 0
|
||||||
|
|| strcmp(name, "askew-range") == 0
|
||||||
|
|| strcmp(name, "dog-ear-size") == 0
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SANE_Int v = atoi(val.c_str());
|
||||||
|
val = std::string((char*)&v, sizeof(v));
|
||||||
|
}
|
||||||
|
else if (strcmp(val.c_str(), "true") == 0)
|
||||||
|
{
|
||||||
|
SANE_Bool b = SANE_TRUE;
|
||||||
|
val = std::string((char*)&b, sizeof(b));
|
||||||
|
}
|
||||||
|
else if (strcmp(val.c_str(), "false") == 0)
|
||||||
|
{
|
||||||
|
SANE_Bool b = SANE_FALSE;
|
||||||
|
val = std::string((char*)&b, sizeof(b));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static const char* title_2_name(const char* title, void* param)
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
const char* name;
|
||||||
|
const char* title;
|
||||||
|
}g_opts[] = { {SANE_STD_OPT_NAME_RESTORE , OPTION_TITLE_HFMRSZ}
|
||||||
|
, {SANE_STD_OPT_NAME_HELP , OPTION_TITLE_BZ}
|
||||||
|
, {SANE_STD_OPT_NAME_IS_MULTI_OUT , OPTION_TITLE_DLSC}
|
||||||
|
, {SANE_STD_OPT_NAME_MULTI_OUT_TYPE , OPTION_TITLE_DLSCLX}
|
||||||
|
, {SANE_STD_OPT_NAME_COLOR_MODE , OPTION_TITLE_YSMS}
|
||||||
|
, {SANE_STD_OPT_NAME_BINARY_THRESHOLD , OPTION_TITLE_HBTXYZ}
|
||||||
|
, {SANE_STD_OPT_NAME_REVERSE_01 , OPTION_TITLE_HBTXFSSC}
|
||||||
|
, {SANE_STD_OPT_NAME_FILTER , OPTION_TITLE_HDHHBTX_CSYZQ}
|
||||||
|
, {SANE_STD_OPT_NAME_RID_MULTIOUT_RED , OPTION_TITLE_24WCSTX_DLSCCH}
|
||||||
|
, {SANE_STD_OPT_NAME_RID_ANSWER_SHEET_RED , OPTION_TITLE_24WCSTX_DTKCH}
|
||||||
|
, {SANE_STD_OPT_NAME_ERASE_BACKGROUND , OPTION_TITLE_BJYC}
|
||||||
|
, {SANE_STD_OPT_NAME_BKG_COLOR_RANGE , OPTION_TITLE_BJSCFDFW}
|
||||||
|
, {SANE_STD_OPT_NAME_SHARPEN , OPTION_TITLE_RHYMH}
|
||||||
|
, {SANE_STD_OPT_NAME_RID_MORR , OPTION_TITLE_QCMW}
|
||||||
|
, {SANE_STD_OPT_NAME_RID_GRID , OPTION_TITLE_CWW}
|
||||||
|
, {SANE_STD_OPT_NAME_ERROR_EXTENSION , OPTION_TITLE_CWKS}
|
||||||
|
, {SANE_STD_OPT_NAME_NOISE_OPTIMIZE , OPTION_TITLE_HBTXZDYH}
|
||||||
|
, {SANE_STD_OPT_NAME_NOISE_SIZE , OPTION_TITLE_ZDYHCC}
|
||||||
|
, {SANE_STD_OPT_NAME_PAPER , OPTION_TITLE_ZZCC}
|
||||||
|
, {SANE_STD_OPT_NAME_CUSTOM_AREA , OPTION_TITLE_ZDYSMQY}
|
||||||
|
, {SANE_STD_OPT_NAME_CUSTOM_AREA_LEFT , OPTION_TITLE_SMQYZCmm}
|
||||||
|
, {SANE_STD_OPT_NAME_CUSTOM_AREA_RIGHT , OPTION_TITLE_SMQYYCmm}
|
||||||
|
, {SANE_STD_OPT_NAME_CUSTOM_AREA_TOP , OPTION_TITLE_SMQYSCmm}
|
||||||
|
, {SANE_STD_OPT_NAME_CUSTOM_AREA_BOTTOM , OPTION_TITLE_SMQYXCmm}
|
||||||
|
, {SANE_STD_OPT_NAME_SIZE_CHECK , OPTION_TITLE_CCJC}
|
||||||
|
, {SANE_STD_OPT_NAME_PAGE , OPTION_TITLE_SMYM}
|
||||||
|
, {SANE_STD_OPT_NAME_DISCARD_BLANK_SENS , OPTION_TITLE_TGKBYLMD}
|
||||||
|
, {SANE_STD_OPT_NAME_RESOLUTION , OPTION_TITLE_FBL}
|
||||||
|
, {SANE_STD_OPT_NAME_TIME_TO_SLEEP , OPTION_TITLE_XMSJ}
|
||||||
|
, {SANE_STD_OPT_NAME_IMAGE_QUALITY , OPTION_TITLE_HZ}
|
||||||
|
, {SANE_STD_OPT_NAME_EXCHANGE ,OPTION_TITLE_JHZFM}
|
||||||
|
, {SANE_STD_OPT_NAME_SPLIT ,OPTION_TITLE_TXCF }
|
||||||
|
, {SANE_STD_OPT_NAME_ANTI_SKEW , OPTION_TITLE_ZDJP}
|
||||||
|
, {SANE_STD_OPT_NAME_IS_CUSTOM_GAMMA , OPTION_TITLE_QYSDQX}
|
||||||
|
, {SANE_STD_OPT_NAME_GAMMA , OPTION_TITLE_JMZ}
|
||||||
|
, {SANE_STD_OPT_NAME_BRIGHTNESS , OPTION_TITLE_LDZ}
|
||||||
|
, {SANE_STD_OPT_NAME_CONTRAST , OPTION_TITLE_DBD}
|
||||||
|
, {SANE_STD_OPT_NAME_IS_PHOTO_MODE , OPTION_TITLE_ZPMS}
|
||||||
|
, {SANE_STD_OPT_NAME_ERASE_BLACK_FRAME , OPTION_TITLE_XCHK}
|
||||||
|
, {SANE_STD_OPT_NAME_DARK_SAMPLE , OPTION_TITLE_SSYZ}
|
||||||
|
, {SANE_STD_OPT_NAME_THRESHOLD , OPTION_TITLE_YZ}
|
||||||
|
, {SANE_STD_OPT_NAME_ANTI_NOISE_LEVEL , OPTION_TITLE_BJKZDJ}
|
||||||
|
, {SANE_STD_OPT_NAME_MARGIN , OPTION_TITLE_BYSJ}
|
||||||
|
, {SANE_STD_OPT_NAME_FILL_BKG_MODE , OPTION_TITLE_BJTCFS}
|
||||||
|
, {SANE_STD_OPT_NAME_IS_ANTI_PERMEATE , OPTION_TITLE_FZST}
|
||||||
|
, {SANE_STD_OPT_NAME_ANTI_PERMEATE_LEVEL , OPTION_TITLE_FZSTDJ}
|
||||||
|
, {SANE_STD_OPT_NAME_RID_HOLE_L , OPTION_TITLE_CKYCZC}
|
||||||
|
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_L , OPTION_TITLE_ZCCKSSFWZFMBL}
|
||||||
|
, {SANE_STD_OPT_NAME_RID_HOLE_R , OPTION_TITLE_CKYCYC}
|
||||||
|
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_R , OPTION_TITLE_YCCKSSFWZFMBL}
|
||||||
|
, {SANE_STD_OPT_NAME_RID_HOLE_T , OPTION_TITLE_CKYCSC}
|
||||||
|
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_T , OPTION_TITLE_SCCKSSFWZFMBL}
|
||||||
|
, {SANE_STD_OPT_NAME_RID_HOLE_B , OPTION_TITLE_CKYCXC}
|
||||||
|
, {SANE_STD_OPT_NAME_SEARCH_HOLE_RANGE_B , OPTION_TITLE_XCCKSSFWZFMBL}
|
||||||
|
, {SANE_STD_OPT_NAME_IS_FILL_COLOR , OPTION_TITLE_SCTC}
|
||||||
|
, {SANE_STD_OPT_NAME_IS_ULTROSONIC_CHECK , OPTION_TITLE_CSBJC}
|
||||||
|
, {SANE_STD_OPT_NAME_DOUBLE_FEED_HANDLE , OPTION_TITLE_SZTPCL}
|
||||||
|
, {SANE_STD_OPT_NAME_IS_CHECK_STAPLE , OPTION_TITLE_ZDJC}
|
||||||
|
, {SANE_STD_OPT_NAME_SCAN_MODE , OPTION_TITLE_SMZS}
|
||||||
|
, {SANE_STD_OPT_NAME_SCAN_COUNT , OPTION_TITLE_SMSL}
|
||||||
|
, {SANE_STD_OPT_NAME_TEXT_DIRECTION , OPTION_TITLE_WGFX}
|
||||||
|
, {SANE_STD_OPT_NAME_IS_ROTATE_BKG_180 , OPTION_TITLE_BMXZ180}
|
||||||
|
, {SANE_STD_OPT_NAME_IS_CHECK_DOG_EAR , OPTION_TITLE_ZJJC}
|
||||||
|
, {SANE_STD_OPT_NAME_DOG_EAR_SIZE , OPTION_TITLE_ZJDX}
|
||||||
|
, {SANE_STD_OPT_NAME_IS_CHECK_ASKEW , OPTION_TITLE_WXJC}
|
||||||
|
, {SANE_STD_OPT_NAME_ASKEW_RANGE , OPTION_TITLE_WXRRD}
|
||||||
|
, {SANE_STD_OPT_NAME_FEED_STRENGTH , OPTION_TITLE_FZQD}
|
||||||
|
, {SANE_STD_OPT_NAME_IS_AUTO_FEED_STRENGTH , OPTION_TITLE_ZDFZQD}
|
||||||
|
, {SANE_STD_OPT_NAME_FEED_STRENGTH_VALUE , OPTION_TITLE_JZSBL}
|
||||||
|
, {SANE_STD_OPT_NAME_WAIT_TO_SCAN , OPTION_TITLE_DZSM}
|
||||||
|
, {SANE_STD_OPT_NAME_FOLD_TYPE , OPTION_TITLE_DZMS}
|
||||||
|
},
|
||||||
|
g_discard[] = { {SANE_STD_OPT_NAME_REVERSE_01 , "\351\273\221\347\231\275\345\233\276\345\203\217\345\217\215\350\211\262\350\276\223\345\207\272\357\274\210\346\255\243\345\270\270\351\242\234\350\211\262\344\270\272\357\274\2320-\351\273\221\350\211\262\357\274\2331-\347\231\275\350\211\262\357\274\211"} // 黑白图像反色输出(正常颜色为:0-黑色;1-白色)
|
||||||
|
, {SANE_STD_OPT_NAME_FILTER , "\347\201\260\345\272\246\346\210\226\351\273\221\347\231\275\345\233\276\345\203\217 - \351\231\244\350\211\262"} // 灰度或黑白图像 - 除色
|
||||||
|
, {SANE_STD_OPT_NAME_IS_AUTO_FEED_STRENGTH , "\350\207\252\345\212\250\346\220\223\347\272\270\345\274\272\345\272\246"} // 自动搓纸强度
|
||||||
|
, {SANE_STD_OPT_NAME_FEED_STRENGTH_VALUE , "\346\220\223\347\272\270\351\230\210\345\200\274"} // " 搓纸阈值"
|
||||||
|
};
|
||||||
|
while (*title == ' ')
|
||||||
|
title++;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < _countof(g_opts); ++i)
|
||||||
|
{
|
||||||
|
if (strcmp(title, g_opts[i].title) == 0)
|
||||||
|
return g_opts[i].name;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < _countof(g_discard); ++i)
|
||||||
|
{
|
||||||
|
if (strcmp(title, g_discard[i].title) == 0)
|
||||||
|
return g_discard[i].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
dev_que() : handle_(nullptr)
|
||||||
|
{}
|
||||||
|
~dev_que()
|
||||||
|
{
|
||||||
|
close_scanner();
|
||||||
|
|
||||||
|
for(auto& v : que_)
|
||||||
|
v.cfg->release();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_old_cfg(const char* conf)
|
||||||
|
{
|
||||||
|
gb::scanner_cfg::UDF func;
|
||||||
|
|
||||||
|
func.func_param = nullptr;
|
||||||
|
func.title2name = &dev_que::title_2_name;
|
||||||
|
func.trans_number = &dev_que::trans_number;
|
||||||
|
|
||||||
|
gb::scanner_cfg::update(conf, &func);
|
||||||
|
}
|
||||||
|
static void apply_scheme(const 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<const SANE_Option_Descriptor*>(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<std::string>& schemes)
|
||||||
|
{
|
||||||
|
schemes.clear();
|
||||||
|
for(auto& v : que_)
|
||||||
|
{
|
||||||
|
if(v.name == scanner_name)
|
||||||
|
{
|
||||||
|
v.cfg->get_all_schemes(schemes);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SANE_Handle handle(void)
|
||||||
|
{
|
||||||
|
return handle_;
|
||||||
|
}
|
||||||
|
std::string opened_scanner_name(void)
|
||||||
|
{
|
||||||
|
return opened_scanner_;
|
||||||
|
}
|
||||||
|
std::string applied_scheme(void)
|
||||||
|
{
|
||||||
|
return applied_scheme_;
|
||||||
|
}
|
||||||
|
int open_scanner(const 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<std::string>& que)
|
||||||
|
{
|
||||||
|
for(auto& v: que_)
|
||||||
|
que.push_back(v.name);
|
||||||
|
}
|
||||||
|
int apply_scheme(const 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<QAction*> actions;
|
||||||
|
|
||||||
|
bool operator==(const QString& menu_title)
|
||||||
|
{
|
||||||
|
return menu->title() == menu_title;
|
||||||
|
}
|
||||||
|
}POPMENU;
|
||||||
|
std::vector<POPMENU> 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<QString>& 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
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include "dialog_device_select.h"
|
||||||
|
#include "ui_dialog_device_select.h"
|
||||||
|
|
||||||
|
Dialog_device_select::Dialog_device_select(const std::vector<DEVQUE>& devs, QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::Dialog_device_select)
|
||||||
|
, m_devId(-1)
|
||||||
|
, m_devs(devs)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
for (int i = 0; i < m_devs.size(); ++i)
|
||||||
|
{
|
||||||
|
ui->listWidget->addItem(QString::fromStdString(m_devs[i].name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog_device_select::~Dialog_device_select()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Dialog_device_select::getDevId()
|
||||||
|
{
|
||||||
|
return m_devId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog_device_select::on_pbtn_ok_clicked()
|
||||||
|
{
|
||||||
|
std::string selectDev = ui->listWidget->currentItem()->text().toStdString();
|
||||||
|
|
||||||
|
for (int i = 0; i < m_devs.size(); ++i)
|
||||||
|
{
|
||||||
|
if (m_devs[i].name == selectDev)
|
||||||
|
{
|
||||||
|
m_devId = m_devs[i].id;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_devId = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
accept();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog_device_select::on_pbtn_cancel_clicked()
|
||||||
|
{
|
||||||
|
m_devId = -1;
|
||||||
|
reject();
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef DIALOG_DEVICE_SELECT_H
|
||||||
|
#define DIALOG_DEVICE_SELECT_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include "twainui.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class Dialog_device_select;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Dialog_device_select : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Dialog_device_select(const std::vector<DEVQUE>& devs, QWidget *parent = nullptr);
|
||||||
|
~Dialog_device_select();
|
||||||
|
|
||||||
|
int getDevId();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_pbtn_ok_clicked();
|
||||||
|
|
||||||
|
void on_pbtn_cancel_clicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::Dialog_device_select *ui;
|
||||||
|
|
||||||
|
std::vector<DEVQUE> m_devs;
|
||||||
|
int m_devId;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DIALOG_DEVICE_SELECT_H
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Dialog_device_select</class>
|
||||||
|
<widget class="QDialog" name="Dialog_device_select">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>342</width>
|
||||||
|
<height>216</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QListWidget" name="listWidget"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pbtn_ok">
|
||||||
|
<property name="text">
|
||||||
|
<string>Ok</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pbtn_cancel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cancel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,65 @@
|
||||||
|
#include "dialog_input.h"
|
||||||
|
#include "ui_dialog_input.h"
|
||||||
|
#include <qmessagebox.h>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
|
||||||
|
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_;
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef DIALOG_INPUT_H
|
||||||
|
#define DIALOG_INPUT_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,85 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Dialog_Input</class>
|
||||||
|
<widget class="QDialog" name="Dialog_Input">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>282</width>
|
||||||
|
<height>82</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="midLineWidth">
|
||||||
|
<number>-1</number>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>输入:</string>
|
||||||
|
</property>
|
||||||
|
<property name="margin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="lineEdit"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Ok</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButton_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cancel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include "dialog_progress_ui.h"
|
||||||
|
#include "ui_dialog_progress_ui.h"
|
||||||
|
|
||||||
|
Dialog_progress_ui *Dialog_progress_ui::m_param = nullptr;
|
||||||
|
|
||||||
|
Dialog_progress_ui::Dialog_progress_ui(std::function<void (ui_result)> callback, std::function<void (int, void *, int)> *notify, QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::Dialog_progress_ui)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
m_callback = callback;
|
||||||
|
*notify = FuncNotify;
|
||||||
|
m_param = this;
|
||||||
|
|
||||||
|
connect(this, SIGNAL(scan_finish(QString)), this, SLOT(on_scan_finish(QString)), Qt::QueuedConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog_progress_ui::~Dialog_progress_ui()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog_progress_ui::on_pbtn_cancelScan_clicked()
|
||||||
|
{
|
||||||
|
m_callback(UI_RESULT_CLOSE_CANCEL);
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog_progress_ui::on_scan_finish(QString finishInfo)
|
||||||
|
{
|
||||||
|
ui->label->setText(finishInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog_progress_ui::FuncNotify(int event, void *msg, int flag)
|
||||||
|
{
|
||||||
|
Dialog_progress_ui *p = (Dialog_progress_ui *)m_param;
|
||||||
|
|
||||||
|
switch (event)
|
||||||
|
{
|
||||||
|
case SANE_EVENT_SCAN_FINISHED:
|
||||||
|
{
|
||||||
|
QString finishInfo((char*)msg);
|
||||||
|
emit p->scan_finish(finishInfo);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
#ifndef DIALOG_PROGRESS_UI_H
|
||||||
|
#define DIALOG_PROGRESS_UI_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include "twainui.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class Dialog_progress_ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Dialog_progress_ui : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Dialog_progress_ui(std::function<void (ui_result)> callback, std::function<void (int, void *, int)> *notify, QWidget *parent = nullptr);
|
||||||
|
~Dialog_progress_ui();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static Dialog_progress_ui *m_param;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void scan_finish(QString finishInfo);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_pbtn_cancelScan_clicked();
|
||||||
|
void on_scan_finish(QString finishInfo);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void FuncNotify(int event, void *msg, int flag);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::Dialog_progress_ui *ui;
|
||||||
|
|
||||||
|
std::function<void (ui_result)> m_callback;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DIALOG_PROGRESS_UI_H
|
|
@ -0,0 +1,95 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Dialog_progress_ui</class>
|
||||||
|
<widget class="QDialog" name="Dialog_progress_ui">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>325</width>
|
||||||
|
<height>166</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Dialog</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pbtn_cancelScan">
|
||||||
|
<property name="text">
|
||||||
|
<string>Cancel Scan</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,62 @@
|
||||||
|
#include "base/HGDef.h"
|
||||||
|
#include "base/HGInc.h"
|
||||||
|
#include "base/HGUtility.h"
|
||||||
|
|
||||||
|
#if defined (HG_CMP_MSC)
|
||||||
|
#include "qmfcapp.hpp"
|
||||||
|
#include "qwinwidget.hpp"
|
||||||
|
|
||||||
|
HINSTANCE g_hInst = NULL;
|
||||||
|
bool g_ownApplication = FALSE;
|
||||||
|
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpvReserved*/)
|
||||||
|
{
|
||||||
|
if (dwReason == DLL_PROCESS_ATTACH)
|
||||||
|
{
|
||||||
|
g_hInst = hInstance;
|
||||||
|
|
||||||
|
HGChar moduleName[512];
|
||||||
|
HGBase_GetModuleName(DllMain, moduleName, 512);
|
||||||
|
HGChar modulePath[512];
|
||||||
|
HGBase_GetFilePath(moduleName, modulePath, 512);
|
||||||
|
|
||||||
|
char *env = getenv("QT_QPA_PLATFORM_PLUGIN_PATH");
|
||||||
|
if (NULL == env)
|
||||||
|
{
|
||||||
|
char newEnv[256];
|
||||||
|
sprintf(newEnv, "QT_QPA_PLATFORM_PLUGIN_PATH=%s", modulePath);
|
||||||
|
putenv(newEnv);
|
||||||
|
}
|
||||||
|
else if (NULL == strstr(env, modulePath))
|
||||||
|
{
|
||||||
|
char *newEnv = new char [strlen(env) + 256];
|
||||||
|
sprintf(newEnv, "QT_QPA_PLATFORM_PLUGIN_PATH=%s;%s", env, modulePath);
|
||||||
|
putenv(newEnv);
|
||||||
|
delete []newEnv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (dwReason == DLL_PROCESS_DETACH)
|
||||||
|
{
|
||||||
|
if (g_ownApplication)
|
||||||
|
delete qApp;
|
||||||
|
g_hInst = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
void __attribute__((constructor)) global_load(void);
|
||||||
|
void __attribute__((destructor)) global_unload(void);
|
||||||
|
|
||||||
|
void global_load(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void global_unload(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,54 @@
|
||||||
|
#include "gaosixy.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef GAOSIXY_H
|
||||||
|
#define GAOSIXY_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
class GaoSiXY
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GaoSiXY();
|
||||||
|
void solve(double **a,int n,double *recv);//用于计算曲线方程
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GAOSIXY_H
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,152 @@
|
||||||
|
#ifndef HG_SETTING_DIALOG_H
|
||||||
|
#define HG_SETTING_DIALOG_H
|
||||||
|
|
||||||
|
#include <QtWidgets>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "HGSaneUI.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(SANE_Handle handle, const SANEAPI* saneApi, bool showScan, QWidget *parent = nullptr);
|
||||||
|
~hg_settingdialog();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void initUi();
|
||||||
|
void updateOpt();
|
||||||
|
void createUI();
|
||||||
|
void updateUIStatus();
|
||||||
|
QVector<QWidget*> find_control(int opt_num);
|
||||||
|
void keyPressEvent(QKeyEvent *e);
|
||||||
|
int get_changed_items(void);
|
||||||
|
int getCloseButtonCliked();
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum closeButtonClicked
|
||||||
|
{
|
||||||
|
closeButtonOk = 0,
|
||||||
|
closeButtonCancel,
|
||||||
|
closeButtonScan,
|
||||||
|
};
|
||||||
|
|
||||||
|
int m_closeButton;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SANEAPI m_saneAPI;
|
||||||
|
SANE_Handle m_devHandle;
|
||||||
|
bool m_showScan;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_qstrFileName;
|
||||||
|
QSettings *m_configIniWrite;
|
||||||
|
QSettings *m_configIniRead;
|
||||||
|
|
||||||
|
private:
|
||||||
|
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<QPair<QPair<int, QVariant>, QString>> m_list_IdValueTitle;
|
||||||
|
QVector<QPair<const void*, QVariant>> m_list_defaultOptions; // default values of device
|
||||||
|
QVector<QPair<QObject*, QObject*>> m_list_sliderSpinbox;
|
||||||
|
QVector<QPair<int, const void*>> m_list_getOpt;
|
||||||
|
QVector<std::string> m_list_deviceNames;
|
||||||
|
QVector<QWidget*> 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_buttonScanClicked();
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,427 @@
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
// Implementation of the QMfcApp classes
|
||||||
|
|
||||||
|
#ifdef QT3_SUPPORT
|
||||||
|
#undef QT3_SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
#undef UNICODE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "qmfcapp.hpp"
|
||||||
|
|
||||||
|
#include <QEventLoop>
|
||||||
|
#include <QAbstractEventDispatcher>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
#ifdef QTWINMIGRATE_WITHMFC
|
||||||
|
#include <afxwin.h>
|
||||||
|
#else
|
||||||
|
#include <qt_windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef QTWINMIGRATE_WITHMFC
|
||||||
|
CWinApp *QMfcApp::mfc_app = 0;
|
||||||
|
char **QMfcApp::mfc_argv = 0;
|
||||||
|
int QMfcApp::mfc_argc = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
#define QT_WA(unicode, ansi) unicode
|
||||||
|
|
||||||
|
QMfcAppEventFilter::QMfcAppEventFilter() : QAbstractNativeEventFilter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QMfcAppEventFilter::nativeEventFilter(const QByteArray &, void *message, long *result)
|
||||||
|
{
|
||||||
|
return static_cast<QMfcApp*>(qApp)->winEventFilter((MSG*)message, result);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! \class QMfcApp qmfcapp.h
|
||||||
|
\brief The QMfcApp class provides merging of the MFC and Qt event loops.
|
||||||
|
|
||||||
|
QMfcApp is responsible for driving both the Qt and MFC event loop.
|
||||||
|
It replaces the standard MFC event loop provided by
|
||||||
|
CWinApp::Run(), and is used instead of the QApplication parent
|
||||||
|
class.
|
||||||
|
|
||||||
|
To replace the MFC event loop reimplement the CWinApp::Run()
|
||||||
|
function in the CWinApp subclass usually created by the MFC
|
||||||
|
Application Wizard, and use either the static run() function, or
|
||||||
|
an instance of QMfcApp created earlier through the static
|
||||||
|
instance() function or the constructor.
|
||||||
|
|
||||||
|
The QMfcApp class also provides a static API pluginInstance() that
|
||||||
|
drives the Qt event loop when loaded into an MFC or Win32 application.
|
||||||
|
This is useful for developing Qt based DLLs or plugins, or if the
|
||||||
|
MFC application's event handling can not be modified.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int modalLoopCount = 0;
|
||||||
|
|
||||||
|
HHOOK hhook;
|
||||||
|
LRESULT CALLBACK QtFilterProc(int nCode, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
if (qApp) {
|
||||||
|
// don't process deferred-deletes while in a modal loop
|
||||||
|
if (modalLoopCount)
|
||||||
|
qApp->sendPostedEvents();
|
||||||
|
else
|
||||||
|
qApp->sendPostedEvents(0, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CallNextHookEx(hhook, nCode, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Inform Qt that a modal loop is about to be entered, and that DeferredDelete
|
||||||
|
events should not be processed. Call this function before calling Win32
|
||||||
|
or MFC functions that enter a modal event loop (i.e. MessageBox).
|
||||||
|
|
||||||
|
This is only required if the Qt UI code hooks into an existing Win32
|
||||||
|
event loop using QMfcApp::pluginInstance.
|
||||||
|
|
||||||
|
\sa exitModalLoop()
|
||||||
|
*/
|
||||||
|
void QMfcApp::enterModalLoop()
|
||||||
|
{
|
||||||
|
++modalLoopCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Inform Qt that a modal loop has been exited, and that DeferredDelete
|
||||||
|
events should not be processed. Call this function after the blocking
|
||||||
|
Win32 or MFC function (i.e. MessageBox) returned.
|
||||||
|
|
||||||
|
This is only required if the Qt UI code hooks into an existing Win32
|
||||||
|
event loop using QMfcApp::pluginInstance.
|
||||||
|
|
||||||
|
\sa enterModalLoop()
|
||||||
|
*/
|
||||||
|
void QMfcApp::exitModalLoop()
|
||||||
|
{
|
||||||
|
--modalLoopCount;
|
||||||
|
Q_ASSERT(modalLoopCount >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
If there is no global QApplication object (i.e. qApp is null) this
|
||||||
|
function creates a QApplication instance and returns true;
|
||||||
|
otherwise it does nothing and returns false.
|
||||||
|
|
||||||
|
The application installs an event filter that drives the Qt event
|
||||||
|
loop while the MFC or Win32 application continues to own the event
|
||||||
|
loop.
|
||||||
|
|
||||||
|
Use this static function if the application event loop code can not be
|
||||||
|
easily modified, or when developing a plugin or DLL that will be loaded
|
||||||
|
into an existing Win32 or MFC application. If \a plugin is non-null then
|
||||||
|
the function loads the respective DLL explicitly to avoid unloading from
|
||||||
|
memory.
|
||||||
|
|
||||||
|
\code
|
||||||
|
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpvReserved)
|
||||||
|
{
|
||||||
|
if (dwReason == DLL_PROCESS_ATTACH)
|
||||||
|
QMfcApp::pluginInstance(hInstance);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
Set \a plugin to 0 when calling this function from within the same executable
|
||||||
|
module.
|
||||||
|
|
||||||
|
If this function is used, call enterModalLoop and exitModalLoop whenever you
|
||||||
|
call a Win32 or MFC function that opens a local event loop.
|
||||||
|
|
||||||
|
\code
|
||||||
|
void Dialog::someSlot()
|
||||||
|
{
|
||||||
|
QMfcApp::enterModalLoop();
|
||||||
|
MessageBox(...);
|
||||||
|
QMfcApp::exitModalLoop();
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
*/
|
||||||
|
bool QMfcApp::pluginInstance(Qt::HANDLE plugin)
|
||||||
|
{
|
||||||
|
if (qApp)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
QT_WA({
|
||||||
|
hhook = SetWindowsHookExW(WH_GETMESSAGE, QtFilterProc, 0, GetCurrentThreadId());
|
||||||
|
}, {
|
||||||
|
hhook = SetWindowsHookExA(WH_GETMESSAGE, QtFilterProc, 0, GetCurrentThreadId());
|
||||||
|
});
|
||||||
|
|
||||||
|
int argc = 0;
|
||||||
|
(void)new QApplication(argc, 0);
|
||||||
|
|
||||||
|
if (plugin) {
|
||||||
|
char filename[256];
|
||||||
|
if (GetModuleFileNameA((HINSTANCE)plugin, filename, 255))
|
||||||
|
LoadLibraryA(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
Q_GLOBAL_STATIC(QMfcAppEventFilter, qmfcEventFilter);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef QTWINMIGRATE_WITHMFC
|
||||||
|
/*!
|
||||||
|
Runs the event loop for both Qt and the MFC application object \a
|
||||||
|
mfcApp, and returns the result. This function calls \c instance()
|
||||||
|
if no QApplication object exists and deletes the object it
|
||||||
|
created.
|
||||||
|
|
||||||
|
Calling this static function in a reimplementation of
|
||||||
|
CWinApp::Run() is the simpliest way to use the QMfcApp class:
|
||||||
|
|
||||||
|
\code
|
||||||
|
int MyMfcApp::Run()
|
||||||
|
{
|
||||||
|
return QMfcApp::run(this);
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
Since a QApplication object must exist before Qt widgets can be
|
||||||
|
created you cannot use this function if you want to use Qt-based
|
||||||
|
user interface elements in, for example, the InitInstance()
|
||||||
|
function of CWinApp. In such cases, create an instance of
|
||||||
|
QApplication explicitly using instance() or the constructor.
|
||||||
|
|
||||||
|
\sa instance()
|
||||||
|
*/
|
||||||
|
int QMfcApp::run(CWinApp *mfcApp)
|
||||||
|
{
|
||||||
|
bool ownInstance = !qApp;
|
||||||
|
if (ownInstance)
|
||||||
|
instance(mfcApp);
|
||||||
|
int result = qApp->exec();
|
||||||
|
|
||||||
|
if (mfcApp) {
|
||||||
|
int mfcRes = mfcApp->ExitInstance();
|
||||||
|
if (mfcRes && !result)
|
||||||
|
result = mfcRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ownInstance)
|
||||||
|
delete qApp;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Creates an instance of QApplication, passing the command line of
|
||||||
|
\a mfcApp to the QApplication constructor, and returns the new
|
||||||
|
object. The returned object must be destroyed by the caller.
|
||||||
|
|
||||||
|
Use this static function if you want to perform additional
|
||||||
|
initializations after creating the application object, or if you
|
||||||
|
want to create Qt GUI elements in the InitInstance()
|
||||||
|
reimplementation of CWinApp:
|
||||||
|
|
||||||
|
\code
|
||||||
|
BOOL MyMfcApp::InitInstance()
|
||||||
|
{
|
||||||
|
// standard MFC initialization
|
||||||
|
// ...
|
||||||
|
|
||||||
|
// This sets the global qApp pointer
|
||||||
|
QMfcApp::instance(this);
|
||||||
|
|
||||||
|
// Qt GUI initialization
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL MyMfcApp::Run()
|
||||||
|
{
|
||||||
|
int result = QMfcApp::run(this);
|
||||||
|
delete qApp;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\sa run()
|
||||||
|
*/
|
||||||
|
QApplication *QMfcApp::instance(CWinApp *mfcApp)
|
||||||
|
{
|
||||||
|
mfc_app = mfcApp;
|
||||||
|
if (mfc_app) {
|
||||||
|
#if defined(UNICODE)
|
||||||
|
QString exeName((QChar*)mfc_app->m_pszExeName, wcslen(mfc_app->m_pszExeName));
|
||||||
|
QString cmdLine((QChar*)mfc_app->m_lpCmdLine, wcslen(mfc_app->m_lpCmdLine));
|
||||||
|
#else
|
||||||
|
QString exeName = QString::fromLocal8Bit(mfc_app->m_pszExeName);
|
||||||
|
QString cmdLine = QString::fromLocal8Bit(mfc_app->m_lpCmdLine);
|
||||||
|
#endif
|
||||||
|
QStringList arglist = QString(exeName + " " + cmdLine).split(' ');
|
||||||
|
|
||||||
|
mfc_argc = arglist.count();
|
||||||
|
mfc_argv = new char*[mfc_argc+1];
|
||||||
|
int a;
|
||||||
|
for (a = 0; a < mfc_argc; ++a) {
|
||||||
|
QString arg = arglist[a];
|
||||||
|
mfc_argv[a] = new char[arg.length()+1];
|
||||||
|
qstrcpy(mfc_argv[a], arg.toLocal8Bit().data());
|
||||||
|
}
|
||||||
|
mfc_argv[a] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new QMfcApp(mfcApp, mfc_argc, mfc_argv);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool qmfc_eventFilter(void *message)
|
||||||
|
{
|
||||||
|
long result = 0;
|
||||||
|
return static_cast<QMfcApp*>(qApp)->winEventFilter((MSG*)message, &result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Creates an instance of QMfcApp. \a mfcApp must point to the
|
||||||
|
existing instance of CWinApp. \a argc and \a argv are passed on
|
||||||
|
to the QApplication constructor.
|
||||||
|
|
||||||
|
Use the static function instance() to automatically use the
|
||||||
|
command line passed to the CWinApp.
|
||||||
|
|
||||||
|
\code
|
||||||
|
QMfcApp *qtApp;
|
||||||
|
|
||||||
|
BOOL MyMfcApp::InitInstance()
|
||||||
|
{
|
||||||
|
// standard MFC initialization
|
||||||
|
|
||||||
|
int argc = ...
|
||||||
|
char **argv = ...
|
||||||
|
|
||||||
|
qtApp = new QMfcApp(this, argc, argv);
|
||||||
|
|
||||||
|
// Qt GUI initialization
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL MyMfcApp::Run()
|
||||||
|
{
|
||||||
|
int result = qtApp->exec();
|
||||||
|
delete qtApp;
|
||||||
|
qtApp = 0;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
\sa instance() run()
|
||||||
|
*/
|
||||||
|
QMfcApp::QMfcApp(CWinApp *mfcApp, int &argc, char **argv)
|
||||||
|
: QApplication(argc, argv), idleCount(0), doIdle(FALSE)
|
||||||
|
{
|
||||||
|
mfc_app = mfcApp;
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
QAbstractEventDispatcher::instance()->installNativeEventFilter(qmfcEventFilter());
|
||||||
|
#else
|
||||||
|
QAbstractEventDispatcher::instance()->setEventFilter(qmfc_eventFilter);
|
||||||
|
#endif
|
||||||
|
setQuitOnLastWindowClosed(false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QMfcApp::QMfcApp(int &argc, char **argv) : QApplication(argc, argv)
|
||||||
|
{
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
QAbstractEventDispatcher::instance()->installNativeEventFilter(qmfcEventFilter());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/*!
|
||||||
|
Destroys the QMfcApp object, freeing all allocated resources.
|
||||||
|
*/
|
||||||
|
QMfcApp::~QMfcApp()
|
||||||
|
{
|
||||||
|
if (hhook) {
|
||||||
|
UnhookWindowsHookEx(hhook);
|
||||||
|
hhook = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef QTWINMIGRATE_WITHMFC
|
||||||
|
for (int a = 0; a < mfc_argc; ++a) {
|
||||||
|
char *arg = mfc_argv[a];
|
||||||
|
delete[] arg;
|
||||||
|
}
|
||||||
|
delete []mfc_argv;
|
||||||
|
|
||||||
|
mfc_argc = 0;
|
||||||
|
mfc_argv = 0;
|
||||||
|
mfc_app = 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
bool QMfcApp::winEventFilter(MSG *msg, long *result)
|
||||||
|
{
|
||||||
|
static bool recursion = false;
|
||||||
|
if (recursion)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
recursion = true;
|
||||||
|
|
||||||
|
QWidget *widget = QWidget::find((WId)msg->hwnd);
|
||||||
|
HWND toplevel = 0;
|
||||||
|
if (widget) {
|
||||||
|
HWND parent = (HWND)widget->winId();
|
||||||
|
while(parent) {
|
||||||
|
toplevel = parent;
|
||||||
|
parent = GetParent(parent);
|
||||||
|
}
|
||||||
|
HMENU menu = toplevel ? GetMenu(toplevel) : 0;
|
||||||
|
if (menu && GetFocus() == msg->hwnd) {
|
||||||
|
if (msg->message == WM_SYSKEYUP && msg->wParam == VK_MENU) {
|
||||||
|
// activate menubar on Alt-up and move focus away
|
||||||
|
SetFocus(toplevel);
|
||||||
|
SendMessage(toplevel, msg->message, msg->wParam, msg->lParam);
|
||||||
|
widget->setFocus();
|
||||||
|
recursion = false;
|
||||||
|
return TRUE;
|
||||||
|
} else if (msg->message == WM_SYSKEYDOWN && msg->wParam != VK_MENU) {
|
||||||
|
SendMessage(toplevel, msg->message, msg->wParam, msg->lParam);
|
||||||
|
SendMessage(toplevel, WM_SYSKEYUP, VK_MENU, msg->lParam);
|
||||||
|
recursion = false;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef QTWINMIGRATE_WITHMFC
|
||||||
|
else if (mfc_app) {
|
||||||
|
MSG tmp;
|
||||||
|
while (doIdle && !PeekMessage(&tmp, 0, 0, 0, PM_NOREMOVE)) {
|
||||||
|
if (!mfc_app->OnIdle(idleCount++))
|
||||||
|
doIdle = FALSE;
|
||||||
|
}
|
||||||
|
if (mfc_app->IsIdleMessage(msg)) {
|
||||||
|
doIdle = TRUE;
|
||||||
|
idleCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mfc_app && mfc_app->PreTranslateMessage(msg)) {
|
||||||
|
recursion = false;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
recursion = false;
|
||||||
|
#if QT_VERSION < 0x050000
|
||||||
|
return QApplication::winEventFilter(msg, result);
|
||||||
|
#else
|
||||||
|
Q_UNUSED(result);
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
|
||||||
|
// Declaration of the QMfcApp classes
|
||||||
|
|
||||||
|
#ifndef QMFCAPP_H
|
||||||
|
#define QMFCAPP_H
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
#if defined(_AFXDLL) && defined(_MSC_VER)
|
||||||
|
#define QTWINMIGRATE_WITHMFC
|
||||||
|
class CWinApp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
#include <QAbstractNativeEventFilter>
|
||||||
|
|
||||||
|
class QMfcAppEventFilter : public QAbstractNativeEventFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QMfcAppEventFilter();
|
||||||
|
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result);
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class QMfcApp : public QApplication
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool pluginInstance(Qt::HANDLE plugin = 0);
|
||||||
|
|
||||||
|
#ifdef QTWINMIGRATE_WITHMFC
|
||||||
|
static int run(CWinApp *mfcApp);
|
||||||
|
static QApplication *instance(CWinApp *mfcApp);
|
||||||
|
QMfcApp(CWinApp *mfcApp, int &argc, char **argv);
|
||||||
|
#endif
|
||||||
|
QMfcApp(int &argc, char **argv);
|
||||||
|
~QMfcApp();
|
||||||
|
|
||||||
|
bool winEventFilter(MSG *msg, long *result);
|
||||||
|
|
||||||
|
static void enterModalLoop();
|
||||||
|
static void exitModalLoop();
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef QTWINMIGRATE_WITHMFC
|
||||||
|
static char ** mfc_argv;
|
||||||
|
static int mfc_argc;
|
||||||
|
static CWinApp *mfc_app;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int idleCount;
|
||||||
|
bool doIdle;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QMFCAPP_H
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,325 @@
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
// Implementation of the QWinHost classes
|
||||||
|
|
||||||
|
#ifdef QT3_SUPPORT
|
||||||
|
#undef QT3_SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "qwinhost.hpp"
|
||||||
|
|
||||||
|
#include <QEvent>
|
||||||
|
#include <qt_windows.h>
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
#define QT_WA(unicode, ansi) unicode
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QWinHost qwinhost.h
|
||||||
|
\brief The QWinHost class provides an API to use native Win32
|
||||||
|
windows in Qt applications.
|
||||||
|
|
||||||
|
QWinHost exists to provide a QWidget that can act as a parent for
|
||||||
|
any native Win32 control. Since QWinHost is a proper QWidget, it
|
||||||
|
can be used as a toplevel widget (e.g. 0 parent) or as a child of
|
||||||
|
any other QWidget.
|
||||||
|
|
||||||
|
QWinHost integrates the native control into the Qt user interface,
|
||||||
|
e.g. handles focus switches and laying out.
|
||||||
|
|
||||||
|
Applications moving to Qt may have custom Win32 controls that will
|
||||||
|
take time to rewrite with Qt. Such applications can use these
|
||||||
|
custom controls as children of QWinHost widgets. This allows the
|
||||||
|
application's user interface to be replaced gradually.
|
||||||
|
|
||||||
|
When the QWinHost is destroyed, and the Win32 window hasn't been
|
||||||
|
set with setWindow(), the window will also be destroyed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Creates an instance of QWinHost. \a parent and \a f are
|
||||||
|
passed on to the QWidget constructor. The widget has by default
|
||||||
|
no background.
|
||||||
|
|
||||||
|
\warning You cannot change the parent widget of the QWinHost instance
|
||||||
|
after the native window has been created, i.e. do not call
|
||||||
|
QWidget::setParent or move the QWinHost into a different layout.
|
||||||
|
*/
|
||||||
|
QWinHost::QWinHost(QWidget *parent, Qt::WindowFlags f)
|
||||||
|
: QWidget(parent, f), wndproc(0),own_hwnd(false), hwnd(0)
|
||||||
|
{
|
||||||
|
setAttribute(Qt::WA_NoBackground);
|
||||||
|
setAttribute(Qt::WA_NoSystemBackground);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Destroys the QWinHost object. If the hosted Win32 window has not
|
||||||
|
been set explicitly using setWindow() the window will be
|
||||||
|
destroyed.
|
||||||
|
*/
|
||||||
|
QWinHost::~QWinHost()
|
||||||
|
{
|
||||||
|
if (wndproc) {
|
||||||
|
#if defined(GWLP_WNDPROC)
|
||||||
|
QT_WA({
|
||||||
|
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc);
|
||||||
|
},{
|
||||||
|
SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)wndproc);
|
||||||
|
})
|
||||||
|
#else
|
||||||
|
QT_WA({
|
||||||
|
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)wndproc);
|
||||||
|
},{
|
||||||
|
SetWindowLongA(hwnd, GWL_WNDPROC, (LONG)wndproc);
|
||||||
|
})
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hwnd && own_hwnd)
|
||||||
|
DestroyWindow(hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Reimplement this virtual function to create and return the native
|
||||||
|
Win32 window. \a parent is the handle to this widget, and \a
|
||||||
|
instance is the handle to the application instance. The returned HWND
|
||||||
|
must be a child of the \a parent HWND.
|
||||||
|
|
||||||
|
The default implementation returns null. The window returned by a
|
||||||
|
reimplementation of this function is owned by this QWinHost
|
||||||
|
instance and will be destroyed in the destructor.
|
||||||
|
|
||||||
|
This function is called by the implementation of polish() if no
|
||||||
|
window has been set explicitly using setWindow(). Call polish() to
|
||||||
|
force this function to be called.
|
||||||
|
|
||||||
|
\sa setWindow()
|
||||||
|
*/
|
||||||
|
HWND QWinHost::createWindow(HWND parent, HINSTANCE instance)
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
Q_UNUSED(instance);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Ensures that the window provided a child of this widget, unless
|
||||||
|
it is a WS_OVERLAPPED window.
|
||||||
|
*/
|
||||||
|
void QWinHost::fixParent()
|
||||||
|
{
|
||||||
|
if (!hwnd)
|
||||||
|
return;
|
||||||
|
if (!::IsWindow(hwnd)) {
|
||||||
|
hwnd = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (::GetParent(hwnd) == (HWND)winId())
|
||||||
|
return;
|
||||||
|
long style = GetWindowLong(hwnd, GWL_STYLE);
|
||||||
|
if (style & WS_OVERLAPPED)
|
||||||
|
return;
|
||||||
|
::SetParent(hwnd, (HWND)winId());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sets the native Win32 window to \a window. If \a window is not a child
|
||||||
|
window of this widget, then it is reparented to become one. If \a window
|
||||||
|
is not a child window (i.e. WS_OVERLAPPED is set), then this function does nothing.
|
||||||
|
|
||||||
|
The lifetime of the window handle will be managed by Windows, QWinHost does not
|
||||||
|
call DestroyWindow. To verify that the handle is destroyed when expected, handle
|
||||||
|
WM_DESTROY in the window procedure.
|
||||||
|
|
||||||
|
\sa window(), createWindow()
|
||||||
|
*/
|
||||||
|
void QWinHost::setWindow(HWND window)
|
||||||
|
{
|
||||||
|
if (hwnd && own_hwnd)
|
||||||
|
DestroyWindow(hwnd);
|
||||||
|
|
||||||
|
hwnd = window;
|
||||||
|
fixParent();
|
||||||
|
|
||||||
|
own_hwnd = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the handle to the native Win32 window, or null if no
|
||||||
|
window has been set or created yet.
|
||||||
|
|
||||||
|
\sa setWindow(), createWindow()
|
||||||
|
*/
|
||||||
|
HWND QWinHost::window() const
|
||||||
|
{
|
||||||
|
return hwnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *getWindowProc(QWinHost *host)
|
||||||
|
{
|
||||||
|
return host ? host->wndproc : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK WinHostProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
QWinHost *widget = qobject_cast<QWinHost*>(QWidget::find((WId)::GetParent(hwnd)));
|
||||||
|
WNDPROC oldproc = (WNDPROC)getWindowProc(widget);
|
||||||
|
if (widget) {
|
||||||
|
switch(msg) {
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
if (::GetFocus() != hwnd && (widget->focusPolicy() & Qt::ClickFocus)) {
|
||||||
|
widget->setFocus(Qt::MouseFocusReason);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_SYSKEYDOWN:
|
||||||
|
case WM_SYSKEYUP:
|
||||||
|
QT_WA({
|
||||||
|
SendMessage((HWND)widget->winId(), msg, wParam, lParam);
|
||||||
|
}, {
|
||||||
|
SendMessageA((HWND)widget->winId(), msg, wParam, lParam);
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_KEYDOWN:
|
||||||
|
if (wParam == VK_TAB) {
|
||||||
|
QT_WA({
|
||||||
|
SendMessage((HWND)widget->winId(), msg, wParam, lParam);
|
||||||
|
}, {
|
||||||
|
SendMessageA((HWND)widget->winId(), msg, wParam, lParam);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_WA({
|
||||||
|
if (oldproc)
|
||||||
|
return CallWindowProc(oldproc, hwnd, msg, wParam, lParam);
|
||||||
|
return DefWindowProc(hwnd,msg,wParam,lParam);
|
||||||
|
}, {
|
||||||
|
if (oldproc)
|
||||||
|
return CallWindowProcA(oldproc, hwnd, msg, wParam, lParam);
|
||||||
|
return DefWindowProcA(hwnd,msg,wParam,lParam);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
bool QWinHost::event(QEvent *e)
|
||||||
|
{
|
||||||
|
switch(e->type()) {
|
||||||
|
case QEvent::Polish:
|
||||||
|
if (!hwnd) {
|
||||||
|
hwnd = createWindow(HWND(winId()), GetModuleHandle(0));
|
||||||
|
fixParent();
|
||||||
|
own_hwnd = hwnd != 0;
|
||||||
|
}
|
||||||
|
if (hwnd && !wndproc && GetParent(hwnd) == (HWND)winId()) {
|
||||||
|
#if defined(GWLP_WNDPROC)
|
||||||
|
QT_WA({
|
||||||
|
wndproc = (void*)GetWindowLongPtr(hwnd, GWLP_WNDPROC);
|
||||||
|
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)WinHostProc);
|
||||||
|
}, {
|
||||||
|
wndproc = (void*)GetWindowLongPtrA(hwnd, GWLP_WNDPROC);
|
||||||
|
SetWindowLongPtrA(hwnd, GWLP_WNDPROC, (LONG_PTR)WinHostProc);
|
||||||
|
})
|
||||||
|
#else
|
||||||
|
QT_WA({
|
||||||
|
wndproc = (void*)GetWindowLong(hwnd, GWL_WNDPROC);
|
||||||
|
SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WinHostProc);
|
||||||
|
}, {
|
||||||
|
wndproc = (void*)GetWindowLongA(hwnd, GWL_WNDPROC);
|
||||||
|
SetWindowLongA(hwnd, GWL_WNDPROC, (LONG)WinHostProc);
|
||||||
|
})
|
||||||
|
#endif
|
||||||
|
|
||||||
|
LONG style;
|
||||||
|
QT_WA({
|
||||||
|
style = GetWindowLong(hwnd, GWL_STYLE);
|
||||||
|
}, {
|
||||||
|
style = GetWindowLongA(hwnd, GWL_STYLE);
|
||||||
|
})
|
||||||
|
if (style & WS_TABSTOP)
|
||||||
|
setFocusPolicy(Qt::FocusPolicy(focusPolicy() | Qt::StrongFocus));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case QEvent::WindowBlocked:
|
||||||
|
if (hwnd)
|
||||||
|
EnableWindow(hwnd, false);
|
||||||
|
break;
|
||||||
|
case QEvent::WindowUnblocked:
|
||||||
|
if (hwnd)
|
||||||
|
EnableWindow(hwnd, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return QWidget::event(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
void QWinHost::showEvent(QShowEvent *e)
|
||||||
|
{
|
||||||
|
QWidget::showEvent(e);
|
||||||
|
|
||||||
|
if (hwnd)
|
||||||
|
SetWindowPos(hwnd, HWND_TOP, 0, 0, width(), height(), SWP_SHOWWINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
void QWinHost::focusInEvent(QFocusEvent *e)
|
||||||
|
{
|
||||||
|
QWidget::focusInEvent(e);
|
||||||
|
|
||||||
|
if (hwnd)
|
||||||
|
::SetFocus(hwnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
void QWinHost::resizeEvent(QResizeEvent *e)
|
||||||
|
{
|
||||||
|
QWidget::resizeEvent(e);
|
||||||
|
|
||||||
|
if (hwnd)
|
||||||
|
SetWindowPos(hwnd, HWND_TOP, 0, 0, width(), height(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
bool QWinHost::nativeEvent(const QByteArray &eventType, void *message, long *result)
|
||||||
|
#else
|
||||||
|
bool QWinHost::winEvent(MSG *msg, long *result)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
MSG *msg = (MSG *)message;
|
||||||
|
#endif
|
||||||
|
switch (msg->message)
|
||||||
|
{
|
||||||
|
case WM_SETFOCUS:
|
||||||
|
if (hwnd) {
|
||||||
|
::SetFocus(hwnd);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
return QWidget::nativeEvent(eventType, message, result);
|
||||||
|
#else
|
||||||
|
return QWidget::winEvent(msg, result);
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
|
||||||
|
// Declaration of the QWinHost classes
|
||||||
|
|
||||||
|
#ifndef QWINHOST_H
|
||||||
|
#define QWINHOST_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class QWinHost : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
QWinHost(QWidget *parent = 0, Qt::WindowFlags f = 0);
|
||||||
|
~QWinHost();
|
||||||
|
|
||||||
|
void setWindow(HWND);
|
||||||
|
HWND window() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual HWND createWindow(HWND parent, HINSTANCE instance);
|
||||||
|
|
||||||
|
bool event(QEvent *e);
|
||||||
|
void showEvent(QShowEvent *);
|
||||||
|
void focusInEvent(QFocusEvent*);
|
||||||
|
void resizeEvent(QResizeEvent*);
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
|
||||||
|
#else
|
||||||
|
bool winEvent(MSG *msg, long *result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
void fixParent();
|
||||||
|
friend void* getWindowProc(QWinHost*);
|
||||||
|
|
||||||
|
void *wndproc;
|
||||||
|
bool own_hwnd;
|
||||||
|
HWND hwnd;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QWINHOST_H
|
|
@ -0,0 +1,359 @@
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
// Implementation of the QWinWidget classes
|
||||||
|
|
||||||
|
#ifdef QT3_SUPPORT
|
||||||
|
#undef QT3_SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
#undef UNICODE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "qmfcapp.hpp"
|
||||||
|
|
||||||
|
#ifdef QTWINMIGRATE_WITHMFC
|
||||||
|
#include <afxwin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <qevent.h>
|
||||||
|
|
||||||
|
#include "qwinwidget.hpp"
|
||||||
|
|
||||||
|
#include <qt_windows.h>
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
#include <QWindow>
|
||||||
|
#include <qpa/qplatformnativeinterface.h>
|
||||||
|
#define QT_WA(unicode, ansi) unicode
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\class QWinWidget qwinwidget.h
|
||||||
|
\brief The QWinWidget class is a Qt widget that can be child of a
|
||||||
|
native Win32 widget.
|
||||||
|
|
||||||
|
The QWinWidget class is the bridge between an existing application
|
||||||
|
user interface developed using native Win32 APIs or toolkits like
|
||||||
|
MFC, and Qt based GUI elements.
|
||||||
|
|
||||||
|
Using QWinWidget as the parent of QDialogs will ensure that
|
||||||
|
modality, placement and stacking works properly throughout the
|
||||||
|
entire application. If the child widget is a top level window that
|
||||||
|
uses the \c WDestructiveClose flag, QWinWidget will destroy itself
|
||||||
|
when the child window closes down.
|
||||||
|
|
||||||
|
Applications moving to Qt can use QWinWidget to add new
|
||||||
|
functionality, and gradually replace the existing interface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Creates an instance of QWinWidget. \a hParentWnd is the handle to
|
||||||
|
the native Win32 parent. If a \a parent is provided the object is
|
||||||
|
owned by that QObject. \a f is passed on to the QWidget constructor.
|
||||||
|
*/
|
||||||
|
QWinWidget::QWinWidget(HWND hParentWnd, QObject *parent, Qt::WindowFlags f)
|
||||||
|
: QWidget(0, f), hParent(hParentWnd), prevFocus(0), reenable_parent(false)
|
||||||
|
{
|
||||||
|
if (parent)
|
||||||
|
QObject::setParent(parent);
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef QTWINMIGRATE_WITHMFC
|
||||||
|
/*!
|
||||||
|
\overload
|
||||||
|
|
||||||
|
Creates an instance of QWinWidget. \a parentWnd is a pointer to an
|
||||||
|
MFC window object. If a \a parent is provided the object is owned
|
||||||
|
by that QObject. \a f is passed on to the QWidget constructor.
|
||||||
|
*/
|
||||||
|
QWinWidget::QWinWidget(CWnd *parentWnd, QObject *parent, Qt::WindowFlags f)
|
||||||
|
: QWidget(0, f), hParent(parentWnd ? parentWnd->m_hWnd : 0), prevFocus(0), reenable_parent(false)
|
||||||
|
{
|
||||||
|
if (parent)
|
||||||
|
QObject::setParent(parent);
|
||||||
|
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void QWinWidget::init()
|
||||||
|
{
|
||||||
|
//Q_ASSERT(hParent);
|
||||||
|
|
||||||
|
if (hParent) {
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
setProperty("_q_embedded_native_parent_handle", WId(hParent));
|
||||||
|
#endif
|
||||||
|
// make the widget window style be WS_CHILD so SetParent will work
|
||||||
|
QT_WA({
|
||||||
|
SetWindowLong((HWND)winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
|
||||||
|
}, {
|
||||||
|
SetWindowLongA((HWND)winId(), GWL_STYLE, WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
|
||||||
|
})
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
QWindow *window = windowHandle();
|
||||||
|
HWND h = static_cast<HWND>(QGuiApplication::platformNativeInterface()->
|
||||||
|
nativeResourceForWindow("handle", window));
|
||||||
|
SetParent(h, hParent);
|
||||||
|
window->setFlags(Qt::FramelessWindowHint);
|
||||||
|
#else
|
||||||
|
SetParent(winId(), hParent);
|
||||||
|
#endif
|
||||||
|
QEvent e(QEvent::EmbeddingControl);
|
||||||
|
QApplication::sendEvent(this, &e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Destroys this object, freeing all allocated resources.
|
||||||
|
*/
|
||||||
|
QWinWidget::~QWinWidget()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Returns the handle of the native Win32 parent window.
|
||||||
|
*/
|
||||||
|
HWND QWinWidget::parentWindow() const
|
||||||
|
{
|
||||||
|
return hParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
void QWinWidget::childEvent(QChildEvent *e)
|
||||||
|
{
|
||||||
|
QObject *obj = e->child();
|
||||||
|
if (obj->isWidgetType()) {
|
||||||
|
if (e->added()) {
|
||||||
|
if (obj->isWidgetType()) {
|
||||||
|
obj->installEventFilter(this);
|
||||||
|
}
|
||||||
|
} else if (e->removed() && reenable_parent) {
|
||||||
|
reenable_parent = false;
|
||||||
|
EnableWindow(hParent, true);
|
||||||
|
obj->removeEventFilter(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QWidget::childEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \internal */
|
||||||
|
void QWinWidget::saveFocus()
|
||||||
|
{
|
||||||
|
if (!prevFocus)
|
||||||
|
prevFocus = ::GetFocus();
|
||||||
|
if (!prevFocus)
|
||||||
|
prevFocus = parentWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Shows this widget. Overrides QWidget::show().
|
||||||
|
|
||||||
|
\sa showCentered()
|
||||||
|
*/
|
||||||
|
void QWinWidget::show()
|
||||||
|
{
|
||||||
|
saveFocus();
|
||||||
|
QWidget::show();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Centers this widget over the native parent window. Use this
|
||||||
|
function to have Qt toplevel windows (i.e. dialogs) positioned
|
||||||
|
correctly over their native parent windows.
|
||||||
|
|
||||||
|
\code
|
||||||
|
QWinWidget qwin(hParent);
|
||||||
|
qwin.center();
|
||||||
|
|
||||||
|
QMessageBox::information(&qwin, "Caption", "Information Text");
|
||||||
|
\endcode
|
||||||
|
|
||||||
|
This will center the message box over the client area of hParent.
|
||||||
|
*/
|
||||||
|
void QWinWidget::center()
|
||||||
|
{
|
||||||
|
const QWidget *child = findChild<QWidget*>();
|
||||||
|
if (child && !child->isWindow()) {
|
||||||
|
qWarning("QWinWidget::center: Call this function only for QWinWidgets with toplevel children");
|
||||||
|
}
|
||||||
|
RECT r;
|
||||||
|
GetWindowRect(hParent, &r);
|
||||||
|
setGeometry((r.right-r.left)/2+r.left, (r.bottom-r.top)/2+r.top,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\obsolete
|
||||||
|
|
||||||
|
Call center() instead.
|
||||||
|
*/
|
||||||
|
void QWinWidget::showCentered()
|
||||||
|
{
|
||||||
|
center();
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
Sets the focus to the window that had the focus before this widget
|
||||||
|
was shown, or if there was no previous window, sets the focus to
|
||||||
|
the parent window.
|
||||||
|
*/
|
||||||
|
void QWinWidget::resetFocus()
|
||||||
|
{
|
||||||
|
if (prevFocus)
|
||||||
|
::SetFocus(prevFocus);
|
||||||
|
else
|
||||||
|
::SetFocus(parentWindow());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \reimp
|
||||||
|
*/
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
bool QWinWidget::nativeEvent(const QByteArray &, void *message, long *)
|
||||||
|
#else
|
||||||
|
bool QWinWidget::winEvent(MSG *msg, long *)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
MSG *msg = (MSG *)message;
|
||||||
|
#endif
|
||||||
|
if (msg->message == WM_SETFOCUS) {
|
||||||
|
Qt::FocusReason reason;
|
||||||
|
if (::GetKeyState(VK_LBUTTON) < 0 || ::GetKeyState(VK_RBUTTON) < 0)
|
||||||
|
reason = Qt::MouseFocusReason;
|
||||||
|
else if (::GetKeyState(VK_SHIFT) < 0)
|
||||||
|
reason = Qt::BacktabFocusReason;
|
||||||
|
else
|
||||||
|
reason = Qt::TabFocusReason;
|
||||||
|
QFocusEvent e(QEvent::FocusIn, reason);
|
||||||
|
QApplication::sendEvent(this, &e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\reimp
|
||||||
|
*/
|
||||||
|
bool QWinWidget::eventFilter(QObject *o, QEvent *e)
|
||||||
|
{
|
||||||
|
QWidget *w = (QWidget*)o;
|
||||||
|
|
||||||
|
switch (e->type()) {
|
||||||
|
case QEvent::WindowDeactivate:
|
||||||
|
if (w->isModal() && w->isHidden())
|
||||||
|
BringWindowToTop(hParent);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEvent::Hide:
|
||||||
|
if (reenable_parent) {
|
||||||
|
EnableWindow(hParent, true);
|
||||||
|
reenable_parent = false;
|
||||||
|
}
|
||||||
|
resetFocus();
|
||||||
|
if (w->testAttribute(Qt::WA_DeleteOnClose) && w->isWindow())
|
||||||
|
deleteLater();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEvent::Show:
|
||||||
|
if (w->isWindow()) {
|
||||||
|
saveFocus();
|
||||||
|
hide();
|
||||||
|
if (w->isModal() && !reenable_parent) {
|
||||||
|
EnableWindow(hParent, false);
|
||||||
|
reenable_parent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QEvent::Close:
|
||||||
|
::SetActiveWindow(hParent);
|
||||||
|
if (w->testAttribute(Qt::WA_DeleteOnClose))
|
||||||
|
deleteLater();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QWidget::eventFilter(o, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \reimp
|
||||||
|
*/
|
||||||
|
void QWinWidget::focusInEvent(QFocusEvent *e)
|
||||||
|
{
|
||||||
|
QWidget *candidate = this;
|
||||||
|
|
||||||
|
switch (e->reason()) {
|
||||||
|
case Qt::TabFocusReason:
|
||||||
|
case Qt::BacktabFocusReason:
|
||||||
|
while (!(candidate->focusPolicy() & Qt::TabFocus)) {
|
||||||
|
candidate = candidate->nextInFocusChain();
|
||||||
|
if (candidate == this) {
|
||||||
|
candidate = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (candidate) {
|
||||||
|
candidate->setFocus(e->reason());
|
||||||
|
if (e->reason() == Qt::BacktabFocusReason || e->reason() == Qt::TabFocusReason) {
|
||||||
|
candidate->setAttribute(Qt::WA_KeyboardFocusChange);
|
||||||
|
candidate->window()->setAttribute(Qt::WA_KeyboardFocusChange);
|
||||||
|
}
|
||||||
|
if (e->reason() == Qt::BacktabFocusReason)
|
||||||
|
QWidget::focusNextPrevChild(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \reimp
|
||||||
|
*/
|
||||||
|
bool QWinWidget::focusNextPrevChild(bool next)
|
||||||
|
{
|
||||||
|
QWidget *curFocus = focusWidget();
|
||||||
|
if (!next) {
|
||||||
|
if (!curFocus->isWindow()) {
|
||||||
|
QWidget *nextFocus = curFocus->nextInFocusChain();
|
||||||
|
QWidget *prevFocus = 0;
|
||||||
|
QWidget *topLevel = 0;
|
||||||
|
while (nextFocus != curFocus) {
|
||||||
|
if (nextFocus->focusPolicy() & Qt::TabFocus) {
|
||||||
|
prevFocus = nextFocus;
|
||||||
|
topLevel = 0;
|
||||||
|
} else if (nextFocus->isWindow()) {
|
||||||
|
topLevel = nextFocus;
|
||||||
|
}
|
||||||
|
nextFocus = nextFocus->nextInFocusChain();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!topLevel) {
|
||||||
|
return QWidget::focusNextPrevChild(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
QWidget *nextFocus = curFocus;
|
||||||
|
while (1) {
|
||||||
|
nextFocus = nextFocus->nextInFocusChain();
|
||||||
|
if (nextFocus->isWindow())
|
||||||
|
break;
|
||||||
|
if (nextFocus->focusPolicy() & Qt::TabFocus) {
|
||||||
|
return QWidget::focusNextPrevChild(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
::SetFocus(hParent);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
|
||||||
|
// Declaration of the QWinWidget classes
|
||||||
|
|
||||||
|
#ifndef QWINWIDGET_H
|
||||||
|
#define QWINWIDGET_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include "qmfcapp.hpp"
|
||||||
|
|
||||||
|
class CWnd;
|
||||||
|
|
||||||
|
class QWinWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
QWinWidget( HWND hParentWnd, QObject *parent = 0, Qt::WindowFlags f = 0 );
|
||||||
|
#ifdef QTWINMIGRATE_WITHMFC
|
||||||
|
QWinWidget( CWnd *parnetWnd, QObject *parent = 0, Qt::WindowFlags f = 0 );
|
||||||
|
#endif
|
||||||
|
~QWinWidget();
|
||||||
|
|
||||||
|
void show();
|
||||||
|
void center();
|
||||||
|
void showCentered();
|
||||||
|
|
||||||
|
HWND parentWindow() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void childEvent( QChildEvent *e );
|
||||||
|
bool eventFilter( QObject *o, QEvent *e );
|
||||||
|
|
||||||
|
bool focusNextPrevChild(bool next);
|
||||||
|
void focusInEvent(QFocusEvent *e);
|
||||||
|
#if QT_VERSION >= 0x050000
|
||||||
|
bool nativeEvent(const QByteArray &eventType, void *message, long *result);
|
||||||
|
#else
|
||||||
|
bool winEvent(MSG *msg, long *result);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
void init();
|
||||||
|
|
||||||
|
void saveFocus();
|
||||||
|
void resetFocus();
|
||||||
|
|
||||||
|
HWND hParent;
|
||||||
|
HWND prevFocus;
|
||||||
|
bool reenable_parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // QWINWIDGET_H
|
|
@ -0,0 +1,315 @@
|
||||||
|
#include "setpicclrtool.h"
|
||||||
|
#include "ui_setpicclrtool.h"
|
||||||
|
#include "widget.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
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<int> gray = getGrayALLPoint();
|
||||||
|
for (size_t i = 0; i < length; i++)
|
||||||
|
table[i] = static_cast<uchar>(gray[static_cast<int>(i)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPicClrTool::getRGBTable(uchar *table, size_t length)
|
||||||
|
{
|
||||||
|
if (length != 768)
|
||||||
|
throw "length is not 768.";
|
||||||
|
|
||||||
|
QVector<int> rgb = getRgbALLPoint();
|
||||||
|
QVector<int> red = getRedALLPoint();
|
||||||
|
QVector<int> green = getGreenALLPoint();
|
||||||
|
QVector<int> 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<uchar>(blue[rgb[static_cast<int>(i)]]);
|
||||||
|
table[i * 3 + 1] = static_cast<uchar>(green[rgb[static_cast<int>(i)]]);
|
||||||
|
table[i * 3 + 2] = static_cast<uchar>(red[rgb[static_cast<int>(i)]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//void setPicClrTool::setGrayTable(const uchar *table, size_t length)
|
||||||
|
//{
|
||||||
|
// QVector<int> gray;
|
||||||
|
// for (size_t i = 0; i < length; i++)
|
||||||
|
// gray[static_cast<int>(i)] = int(table[i]);
|
||||||
|
// //ui->widget->setGrayALLPoint(gray);
|
||||||
|
//}
|
||||||
|
|
||||||
|
//void setPicClrTool::setRGBTable(const uchar *table, size_t length)
|
||||||
|
//{
|
||||||
|
// QVector<int> rgb;
|
||||||
|
// QVector<int> red;
|
||||||
|
// QVector<int> green;
|
||||||
|
// QVector<int> 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<QList<QPoint> > setPicClrTool::getRGBKeyTable()
|
||||||
|
{
|
||||||
|
QVector<QList<QPoint>> plv;
|
||||||
|
plv.append(getRgbKeyPoint());
|
||||||
|
plv.append(getRedKeyPoint());
|
||||||
|
plv.append(getGreenKeyPoint());
|
||||||
|
plv.append(getBlueKeyPoint());
|
||||||
|
return plv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPicClrTool::setRGBKeyTable(QVector<QList<QPoint> > &plv)
|
||||||
|
{
|
||||||
|
setRgbKeyPoint(plv[0]);
|
||||||
|
setRedKeyPoint(plv[1]);
|
||||||
|
setGreenKeyPoint(plv[2]);
|
||||||
|
setBlueKeyPoint(plv[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> setPicClrTool::getGrayKeyTable()
|
||||||
|
{
|
||||||
|
return getGrayKeyPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPicClrTool::setGrayKeyTable(QList<QPoint> &plv)
|
||||||
|
{
|
||||||
|
setGrayKeyPoint(plv);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> setPicClrTool::getRgbALLPoint()
|
||||||
|
{
|
||||||
|
return ui->widget->getRgbALLPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> setPicClrTool::getRgbKeyPoint() const
|
||||||
|
{
|
||||||
|
qDebug() << "setRgb" << ui->widget->getRgbKeyPoint();
|
||||||
|
return ui->widget->getRgbKeyPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPicClrTool::setRgbKeyPoint(const QList<QPoint> &pVec)
|
||||||
|
{
|
||||||
|
qDebug() << "setRgb" << pVec;
|
||||||
|
ui->widget->setRgbKeyPoint(pVec);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> setPicClrTool::getRedKeyPoint() const
|
||||||
|
{
|
||||||
|
return ui->widget->getRedKeyPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPicClrTool::setRedKeyPoint(const QList<QPoint> &pVec)
|
||||||
|
{
|
||||||
|
ui->widget->setRedKeyPoint(pVec);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> setPicClrTool::getBlueKeyPoint() const
|
||||||
|
{
|
||||||
|
return ui->widget->getBlueKeyPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPicClrTool::setBlueKeyPoint(const QList<QPoint> &pVec)
|
||||||
|
{
|
||||||
|
ui->widget->setBlueKeyPoint(pVec);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> setPicClrTool::getGreenKeyPoint() const
|
||||||
|
{
|
||||||
|
return ui->widget->getGreenKeyPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPicClrTool::setGreenKeyPoint(const QList<QPoint> &pVec)
|
||||||
|
{
|
||||||
|
ui->widget->setGreenKeyPoint(pVec);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> setPicClrTool::getGrayKeyPoint() const
|
||||||
|
{
|
||||||
|
return ui->widget->getGrayKeyPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPicClrTool::setGrayKeyPoint(const QList<QPoint> &pVec)
|
||||||
|
{
|
||||||
|
ui->widget->setGrayKeyPoint(pVec);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> setPicClrTool::getRedALLPoint()
|
||||||
|
{
|
||||||
|
return ui->widget->getRedALLPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> setPicClrTool::getBlueALLPoint()
|
||||||
|
{
|
||||||
|
return ui->widget->getBlueALLPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> setPicClrTool::getGreenALLPoint()
|
||||||
|
{
|
||||||
|
return ui->widget->getGreenALLPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> 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();
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
#ifndef SETPICCLRTOOL_H
|
||||||
|
#define SETPICCLRTOOL_H
|
||||||
|
|
||||||
|
//#include "colorlinesetdef.h"
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
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<QList<QPoint>> getRGBKeyTable();
|
||||||
|
void setRGBKeyTable(QVector<QList<QPoint>>& plv);
|
||||||
|
QList<QPoint> getGrayKeyTable();
|
||||||
|
void setGrayKeyTable(QList<QPoint> &plv);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVector<int> getRgbALLPoint();
|
||||||
|
QVector<int> getRedALLPoint();
|
||||||
|
QVector<int> getBlueALLPoint();
|
||||||
|
QVector<int> getGreenALLPoint();
|
||||||
|
QVector<int> getGrayALLPoint();
|
||||||
|
|
||||||
|
QList<QPoint> getRgbKeyPoint()const;
|
||||||
|
void setRgbKeyPoint(const QList<QPoint>& pVec);
|
||||||
|
QList<QPoint> getRedKeyPoint()const;
|
||||||
|
void setRedKeyPoint(const QList<QPoint>& pVec);
|
||||||
|
QList<QPoint> getBlueKeyPoint()const;
|
||||||
|
void setBlueKeyPoint(const QList<QPoint>& pVec);
|
||||||
|
QList<QPoint> getGreenKeyPoint()const;
|
||||||
|
void setGreenKeyPoint(const QList<QPoint>& pVec);
|
||||||
|
QList<QPoint> getGrayKeyPoint()const;
|
||||||
|
void setGrayKeyPoint(const QList<QPoint>& 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<QPoint> linePoint;
|
||||||
|
QList<QPoint> greenLine;
|
||||||
|
QList<QPoint> redLine;
|
||||||
|
QList<QPoint> blueLine;
|
||||||
|
QList<QPoint> rgbLine;
|
||||||
|
QList<QPoint> grayLine;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SETPICCLRTOOL_H
|
|
@ -0,0 +1,167 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>setPicClrTool</class>
|
||||||
|
<widget class="QWidget" name="setPicClrTool">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>259</width>
|
||||||
|
<height>341</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>自定义色调曲线</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,1,0,0">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="comboBox">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>自定义</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>负片(RGB)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>彩色负片(RGB)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>较暗(RGB)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>较亮(RGB)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2" stretch="4,2,1">
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="colorSetCmb">
|
||||||
|
<property name="mouseTracking">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>RGB</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>灰</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>红</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>蓝</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>绿</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="pushButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>初始化</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Widget" name="widget" native="true">
|
||||||
|
<property name="mouseTracking">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::StrongFocus</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>输入:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="inputEdt">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="text">
|
||||||
|
<string>输出:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="outputEdt">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>Widget</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header location="global">widget.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
|
@ -0,0 +1,99 @@
|
||||||
|
#include "twainui.h"
|
||||||
|
#include "dialog_device_select.h"
|
||||||
|
#include "dialog_progress_ui.h"
|
||||||
|
#include "hg_settingdialog.h"
|
||||||
|
|
||||||
|
#ifdef HG_CMP_MSC
|
||||||
|
#include "qwinwidget.hpp"
|
||||||
|
extern HINSTANCE g_hInst;
|
||||||
|
extern bool g_ownApplication;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int choose_scanner(const std::vector<DEVQUE> &devs)
|
||||||
|
{
|
||||||
|
Dialog_device_select dlg(devs);
|
||||||
|
if (dlg.exec())
|
||||||
|
{
|
||||||
|
return dlg.getDevId();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *apply_current_config(const char *dev_name, SANE_Handle device, LPSANEAPI api)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void twain_ui_free(void *buf)
|
||||||
|
{
|
||||||
|
if (buf != nullptr)
|
||||||
|
{
|
||||||
|
delete buf;
|
||||||
|
buf = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int show_setting_ui(SANE_Handle device, HWND parent, LPSANEAPI api, bool with_scan)
|
||||||
|
{
|
||||||
|
if (nullptr == api || nullptr == device)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
QWidget *qParent = nullptr;
|
||||||
|
#ifdef HG_CMP_MSC
|
||||||
|
if (!g_ownApplication)
|
||||||
|
g_ownApplication = QMfcApp::pluginInstance(g_hInst);
|
||||||
|
QWinWidget win(parent);
|
||||||
|
if (nullptr != parent)
|
||||||
|
{
|
||||||
|
win.showCentered();
|
||||||
|
qParent = &win;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
qParent = parent;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QTranslator translator;
|
||||||
|
int cp = lang_get_cur_code_page();
|
||||||
|
if (20127 == cp)
|
||||||
|
translator.load(":translation/TwainUI_zh_EN.qm");
|
||||||
|
else
|
||||||
|
translator.load(":translation/TwainUI_zh_CN.qm");
|
||||||
|
QCoreApplication::installTranslator(&translator);
|
||||||
|
|
||||||
|
hg_settingdialog dlg(device, api, with_scan, qParent);
|
||||||
|
dlg.exec();
|
||||||
|
QCoreApplication::removeTranslator(&translator);
|
||||||
|
|
||||||
|
int ret = dlg.getCloseButtonCliked();
|
||||||
|
if (ret == dlg.closeButtonScan)
|
||||||
|
return UI_RESULT_START_SCAN;
|
||||||
|
else if (ret == dlg.closeButtonCancel)
|
||||||
|
return UI_RESULT_CLOSE_CANCEL;
|
||||||
|
else
|
||||||
|
return UI_RESULT_CLOSE_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int show_progress_ui(HWND parent, std::function<void (ui_result)> callback, std::function<void (int, void *, int)> *notify)
|
||||||
|
{
|
||||||
|
QWidget *qParent = nullptr;
|
||||||
|
#ifdef HG_CMP_MSC
|
||||||
|
if (!g_ownApplication)
|
||||||
|
g_ownApplication = QMfcApp::pluginInstance(g_hInst);
|
||||||
|
QWinWidget win(parent);
|
||||||
|
if (nullptr != parent)
|
||||||
|
{
|
||||||
|
win.showCentered();
|
||||||
|
qParent = &win;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
qParent = parent;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Dialog_progress_ui dlg(callback, notify, qParent);
|
||||||
|
dlg.show();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <functional>
|
||||||
|
#include "sane/sane_ex.h"
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
typedef struct _dev_que
|
||||||
|
{
|
||||||
|
int id; // ID,用户选中后返回该值
|
||||||
|
std::string name; // 设备名称
|
||||||
|
std::string sn; // 设备序列号
|
||||||
|
}DEVQUE;
|
||||||
|
|
||||||
|
// 功能: 选择多个同型设备中的一个,模态
|
||||||
|
//
|
||||||
|
// 参数: devs - 设备队列列表
|
||||||
|
//
|
||||||
|
// 返回: 用户选择的设备所对应的,DEVQUE::id;或者-1代表用户放弃选择设备
|
||||||
|
int choose_scanner(const std::vector<DEVQUE>& devs); // blocked. return selected DEVQUE::id or -1 if user cancelled
|
||||||
|
|
||||||
|
|
||||||
|
// 功能: 应用当前设备对应的用户配置,同步
|
||||||
|
//
|
||||||
|
// 参数: dev_name - 设备名称
|
||||||
|
//
|
||||||
|
// device - 设备打开的句柄
|
||||||
|
//
|
||||||
|
// api - sane_xxx API函数指针
|
||||||
|
//
|
||||||
|
// 返回: 当前设备配置方案的名称。返回指针通过调用函数twain_ui_free来释放
|
||||||
|
char* apply_current_config(const char* dev_name, SANE_Handle device, LPSANEAPI api);
|
||||||
|
|
||||||
|
// 功能: 释放由界面模块返回的动态分配的内存,同步
|
||||||
|
//
|
||||||
|
// 参数: buf - 内存地址
|
||||||
|
//
|
||||||
|
// 返回: 无
|
||||||
|
void twain_ui_free(void* buf);
|
||||||
|
|
||||||
|
enum ui_result
|
||||||
|
{
|
||||||
|
UI_RESULT_FAILED = -1, // 一般用于界面初始化失败
|
||||||
|
UI_RESULT_OK, // 界面正常显示
|
||||||
|
UI_RESULT_CLOSE_NORMAL, // 界面正常关闭
|
||||||
|
UI_RESULT_CLOSE_CANCEL, // 用户取消操作,如取消扫描……
|
||||||
|
UI_RESULT_START_SCAN, // 用户点击了开始扫描
|
||||||
|
};
|
||||||
|
// 功能: 释放由界面模块返回的动态分配的内存,模态
|
||||||
|
//
|
||||||
|
// 参数: device - 当前打开的设备句柄
|
||||||
|
//
|
||||||
|
// parent - 父窗口句柄
|
||||||
|
//
|
||||||
|
// api - sane_xxx API函数指针
|
||||||
|
//
|
||||||
|
// with_scan - 是否显示“扫描”按钮
|
||||||
|
//
|
||||||
|
// 返回: ui_result 类型, UI_RESULT_CLOSE_NORMAL or UI_RESULT_START_SCAN
|
||||||
|
int show_setting_ui(SANE_Handle device, HWND parent, LPSANEAPI api, bool with_scan/*是否显示“扫描”按钮*/);
|
||||||
|
|
||||||
|
// 功能: 显示扫描进度界面,非模态
|
||||||
|
//
|
||||||
|
// 参数: parent - 父窗口句柄
|
||||||
|
//
|
||||||
|
// callback - 用户界面操作事件回调(主要为取消扫描事件)
|
||||||
|
//
|
||||||
|
// notify - ui接收进度通知函数,外部通过该返回的函数来通知当前扫描进度或事件
|
||||||
|
// notify events: SANE_EVENT_WORKING - void*: unused, be NULL, flag - unused, be 0
|
||||||
|
// SANE_EVENT_SCAN_FINISHED - void*: (utf8*)message, flag - error code (0 is success)
|
||||||
|
// SANE_EVENT_USB_DATA_RECEIVED- void* unused, be NULL, flag - unused, be 0
|
||||||
|
// SANE_EVENT_IMAGE_OK - void* unused, be NULL, flag - unused, be 0
|
||||||
|
//
|
||||||
|
// 返回: ui_result 类型, UI_RESULT_FAILED or UI_RESULT_OK
|
||||||
|
int show_progress_ui(HWND parent, std::function<void(ui_result)> callback, std::function<void(int/*event*/, void*/*msg*/, int/*flag*/)>* notify);
|
|
@ -0,0 +1,855 @@
|
||||||
|
#include "widget.h"
|
||||||
|
#include "ui_widget.h"
|
||||||
|
#include "gaosixy.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QVector>
|
||||||
|
#include <QDebug>
|
||||||
|
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<QPoint> &plst)
|
||||||
|
{
|
||||||
|
rgbLine = QList<QPoint>(plst);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> Widget::getLstPnt_RGB() const
|
||||||
|
{
|
||||||
|
return rgbLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setLstPnt_RED(const QList<QPoint> &plst)
|
||||||
|
{
|
||||||
|
redLine = QList<QPoint>(plst);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setLstPnt_BLUE(const QList<QPoint> &plst)
|
||||||
|
{
|
||||||
|
blueLine = QList<QPoint>(plst);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> Widget::getLstPnt_BLUE() const
|
||||||
|
{
|
||||||
|
return blueLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setLstPnt_GREEN(const QList<QPoint> &plst)
|
||||||
|
{
|
||||||
|
greenLine = QList<QPoint>(plst);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> Widget::getLstPnt_GREEN() const
|
||||||
|
{
|
||||||
|
return greenLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setLstPnt_GRAY(const QList<QPoint> &plst)
|
||||||
|
{
|
||||||
|
grayLine = QList<QPoint>(plst);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> Widget::getLstPnt_GRAY() const
|
||||||
|
{
|
||||||
|
return grayLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> Widget::getRgbALLPoint()
|
||||||
|
{
|
||||||
|
return rgbALLPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> Widget::getRgbKeyPoint() const
|
||||||
|
{
|
||||||
|
return rgbLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setRgbKeyPoint(const QList<QPoint> &pLst)
|
||||||
|
{
|
||||||
|
if(pLst.size() > 4) return;
|
||||||
|
rgbLine = QList<QPoint>(pLst);
|
||||||
|
pointLst.clear();
|
||||||
|
pointLst = QList<QPoint>(rgbLine);
|
||||||
|
drawLineFromPoint(rgbLine, RGB);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> Widget::getRedALLPoint()
|
||||||
|
{
|
||||||
|
return redALLPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> Widget::getRedKeyPoint() const
|
||||||
|
{
|
||||||
|
return redLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setRedKeyPoint(const QList<QPoint> &pLst)
|
||||||
|
{
|
||||||
|
if(pLst.size() > 4) return;
|
||||||
|
redLine = QList<QPoint>(pLst);
|
||||||
|
drawLineFromPoint(redLine, RED);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> Widget::getBlueALLPoint()
|
||||||
|
{
|
||||||
|
return blueALLPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> Widget::getBlueKeyPoint() const
|
||||||
|
{
|
||||||
|
return blueLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setBlueKeyPoint(const QList<QPoint> &pLst)
|
||||||
|
{
|
||||||
|
if(pLst.size() > 4) return;
|
||||||
|
blueLine = QList<QPoint>(pLst);
|
||||||
|
drawLineFromPoint(blueLine, BLUE);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> Widget::getGreenALLPoint()
|
||||||
|
{
|
||||||
|
return greenALLPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> Widget::getGreenKeyPoint() const
|
||||||
|
{
|
||||||
|
return greenLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setGreenKeyPoint(const QList<QPoint> &pLst)
|
||||||
|
{
|
||||||
|
if(pLst.size() > 4) return;
|
||||||
|
greenLine = QList<QPoint>(pLst);
|
||||||
|
drawLineFromPoint(greenLine, GREEN);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> Widget::getGrayALLPoint()
|
||||||
|
{
|
||||||
|
return grayALLPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QPoint> Widget::getGrayKeyPoint() const
|
||||||
|
{
|
||||||
|
return grayLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setGrayKeyPoint(const QList<QPoint> &pLst)
|
||||||
|
{
|
||||||
|
if(pLst.size() > 4) return;
|
||||||
|
grayLine = QList<QPoint>(pLst);
|
||||||
|
pointLst.clear();
|
||||||
|
pointLst = QList<QPoint>(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<int> &hist)
|
||||||
|
{
|
||||||
|
rgbBackColor = QVector<int>(hist);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> Widget::getHist_RED() const
|
||||||
|
{
|
||||||
|
return redBackColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setHist_RED(const QVector<int> &hist)
|
||||||
|
{
|
||||||
|
redBackColor = QVector<int>(hist);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> Widget::getHist_RGB() const
|
||||||
|
{
|
||||||
|
return rgbBackColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setHist_GREEN(const QVector<int> &hist)
|
||||||
|
{
|
||||||
|
greenBackColor = QVector<int>(hist);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> Widget::getHist_GREEN() const
|
||||||
|
{
|
||||||
|
return greenBackColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setHist_BLUE(const QVector<int> &hist)
|
||||||
|
{
|
||||||
|
blueBackColor = QVector<int>(hist);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> Widget::getHist_BLUE() const
|
||||||
|
{
|
||||||
|
return blueBackColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setHist_GRAY(const QVector<int> &hist)
|
||||||
|
{
|
||||||
|
grayBackColor = QVector<int>(hist);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<int> 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<int> &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<qreal> dashes;
|
||||||
|
qreal space = 3;
|
||||||
|
dashes << 5 << space << 5 <<space;
|
||||||
|
QPen pen;
|
||||||
|
pen.setDashPattern(dashes);
|
||||||
|
pen.setWidth(1);
|
||||||
|
painter.setPen(pen);
|
||||||
|
painter.drawLine(i,300,i,0);
|
||||||
|
painter.drawLine(0,i,300,i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QLine line(0,0,255,255);
|
||||||
|
painter.drawLine(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::drawLineFromPoint(QList<QPoint> &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<double> 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<QPoint>(pointLst);
|
||||||
|
}
|
||||||
|
else if(selectCol == RED){
|
||||||
|
redLine.clear();
|
||||||
|
redLine = QList<QPoint>(pointLst);
|
||||||
|
}else if(selectCol == BLUE){
|
||||||
|
blueLine.clear();
|
||||||
|
blueLine = QList<QPoint>(pointLst);
|
||||||
|
}else if(selectCol == RGB){
|
||||||
|
rgbLine.clear();
|
||||||
|
rgbLine = QList<QPoint>(pointLst);
|
||||||
|
}else if(selectCol == GRAY){
|
||||||
|
grayLine.clear();
|
||||||
|
grayLine = QList<QPoint>(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<int> &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<unsigned char> 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<QPoint>(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<QPoint>(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<QPoint>(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<QPoint>(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<QPoint>(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<int> &all)
|
||||||
|
{
|
||||||
|
allLinePntSet = QVector<int>(all);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
#ifndef WIDGET_H
|
||||||
|
#define WIDGET_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
//#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<QPoint>& plst); //设置生成RGB曲线的关键点(<=4)
|
||||||
|
QList<QPoint> getLstPnt_RGB()const; //获取生成RGB曲线的关键点
|
||||||
|
void setLstPnt_RED(const QList<QPoint>& plst);
|
||||||
|
QList<QPoint> getLstPnt_RED()const;
|
||||||
|
void setLstPnt_BLUE(const QList<QPoint>& plst);
|
||||||
|
QList<QPoint> getLstPnt_BLUE()const;
|
||||||
|
void setLstPnt_GREEN(const QList<QPoint>& plst);
|
||||||
|
QList<QPoint> getLstPnt_GREEN()const;
|
||||||
|
void setLstPnt_GRAY(const QList<QPoint>& plst);
|
||||||
|
QList<QPoint> getLstPnt_GRAY()const;
|
||||||
|
|
||||||
|
QVector<int> getRgbALLPoint();
|
||||||
|
QList<QPoint> getRgbKeyPoint()const;
|
||||||
|
void setRgbKeyPoint(const QList<QPoint>& pVec);
|
||||||
|
QVector<int> getRedALLPoint();
|
||||||
|
QList<QPoint> getRedKeyPoint()const;
|
||||||
|
void setRedKeyPoint(const QList<QPoint>& pVec);
|
||||||
|
QVector<int> getBlueALLPoint();
|
||||||
|
QList<QPoint> getBlueKeyPoint()const;
|
||||||
|
void setBlueKeyPoint(const QList<QPoint>& pVec);
|
||||||
|
QVector<int> getGreenALLPoint();
|
||||||
|
QList<QPoint> getGreenKeyPoint()const;
|
||||||
|
void setGreenKeyPoint(const QList<QPoint>& pVec);
|
||||||
|
QVector<int> getGrayALLPoint();
|
||||||
|
QList<QPoint> getGrayKeyPoint()const;
|
||||||
|
void setGrayKeyPoint(const QList<QPoint>& pVec);
|
||||||
|
|
||||||
|
void setHist_RGB(const QVector<int>& hist);//设置RGB的背景直方图
|
||||||
|
QVector<int> getHist_RGB()const;//获取RGB的背景直方图
|
||||||
|
void setHist_RED(const QVector<int>& hist);
|
||||||
|
QVector<int> getHist_RED()const;
|
||||||
|
void setHist_BLUE(const QVector<int>& hist);
|
||||||
|
QVector<int> getHist_BLUE()const;
|
||||||
|
void setHist_GREEN(const QVector<int>& hist);
|
||||||
|
QVector<int> getHist_GREEN()const;
|
||||||
|
void setHist_GRAY(const QVector<int>& hist);
|
||||||
|
QVector<int> getHist_GRAY()const;
|
||||||
|
|
||||||
|
void getCurLineLUT(uchar* table, size_t length = 256);//获取当前曲线上的所有点并存入table
|
||||||
|
QVector<unsigned char> 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<int>& 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<int>&);//画背景直方图
|
||||||
|
void drawBackColorBySlc(QPainter&);//画不同的背景直方图
|
||||||
|
void drawCoorScale(QPainter&);//画虚线刻度
|
||||||
|
void drawLineFromPoint(QList<QPoint> &plst, const int &col);//根据多点求出曲线方程,并画出曲线
|
||||||
|
void drawAllPoint(QPainter&);//画出生成曲线的关键点
|
||||||
|
void drawCurveByColor(QPainter&);//画不同的颜色曲线
|
||||||
|
void drawLineByVector(QPainter&,QVector<int>&);//将数组的所有点连接绘制曲线
|
||||||
|
int caculateAllMi(int num,int n);//计算num的n次方的值
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::Widget *ui;
|
||||||
|
QVector<int> rgbBackColor;
|
||||||
|
QVector<int> redBackColor;
|
||||||
|
QVector<int> blueBackColor;
|
||||||
|
QVector<int> greenBackColor;
|
||||||
|
QVector<int> grayBackColor;
|
||||||
|
QVector<int> rgbALLPoint;
|
||||||
|
QVector<int> redALLPoint;
|
||||||
|
QVector<int> blueALLPoint;
|
||||||
|
QVector<int> greenALLPoint;
|
||||||
|
QVector<int> grayALLPoint;
|
||||||
|
QVector<int> allLinePntSet;
|
||||||
|
QVector<unsigned char> linePoints;
|
||||||
|
|
||||||
|
//QList<QPoint> points;
|
||||||
|
QList<QPoint> pointLst;
|
||||||
|
QList<QPoint> linePoint;
|
||||||
|
QList<QPoint> greenLine;
|
||||||
|
QList<QPoint> redLine;
|
||||||
|
QList<QPoint> blueLine;
|
||||||
|
QList<QPoint> rgbLine;
|
||||||
|
QList<QPoint> grayLine;
|
||||||
|
QColor color;
|
||||||
|
|
||||||
|
unsigned char allLinePoints[256];
|
||||||
|
bool leftMouseMv;
|
||||||
|
bool newPoint;
|
||||||
|
bool clickLine;
|
||||||
|
int dragPoint;
|
||||||
|
int selectCol;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // WIDGET_H
|
|
@ -0,0 +1,91 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Widget</class>
|
||||||
|
<widget class="QWidget" name="Widget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>556</width>
|
||||||
|
<height>484</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Widget</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout" rowstretch="50,1" columnstretch="1,50">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QWidget" name="widget" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="mouseTracking">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::WheelFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">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))}</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QWidget" name="table" native="true">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="mouseTracking">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::NoFocus</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QWidget" name="widget_2" native="true">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">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))}</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Loading…
Reference in New Issue