From 1b734fdf37026244cda44a74bd7400ec56e999d6 Mon Sep 17 00:00:00 2001
From: i7-8700 <1281261856@qq.com>
Date: Thu, 5 Dec 2019 23:43:33 +0800
Subject: [PATCH] qt

---
 jlib/qt/View/HttpDlg.h                        |  62 +--
 test/qt_test/jlib/qt/Ctrl/moc_ThreadCtrl.cpp  | 172 ---------
 test/qt_test/jlib/qt/View/moc_BgColorBtn.cpp  | 139 -------
 test/qt_test/jlib/qt/View/moc_IconBtn.cpp     | 191 ----------
 test/qt_test/jlib/qt/View/moc_LoadingView.cpp | 142 -------
 test/qt_test/jlib/qt/View/moc_PageTitle.cpp   | 165 --------
 test/qt_test/jlib/qt/View/moc_RndButton.cpp   | 129 -------
 test/qt_test/qt/Ctrl/ThreadCtrl.h             |  56 +++
 test/qt_test/qt/ErrorCode.h                   |  84 ++++
 test/qt_test/qt/Model/ThreadModel.h           |  28 ++
 test/qt_test/qt/QtDebug.h                     |  14 +
 test/qt_test/qt/QtDebugOutput.h               |  41 ++
 test/qt_test/qt/QtPathHelper.h                |  84 ++++
 test/qt_test/qt/QtStylesheet.h                | 360 ++++++++++++++++++
 test/qt_test/qt/QtUtils.h                     | 127 ++++++
 test/qt_test/qt/View/BgColorBtn.h             |  75 ++++
 test/qt_test/qt/View/HttpDlg.h                | 212 +++++++++++
 test/qt_test/qt/View/HttpDlgErrorCode.h       |  57 +++
 test/qt_test/qt/View/IconBtn.h                | 150 ++++++++
 test/qt_test/qt/View/LoadingView.h            | 194 ++++++++++
 test/qt_test/qt/View/PageTitle.h              | 163 ++++++++
 test/qt_test/qt/View/RndButton.h              | 111 ++++++
 test/qt_test/qt/signal_slot.h                 |   7 +
 test/qt_test/qt_test.cpp                      |  30 +-
 test/qt_test/qt_test.vcxproj                  |  41 +-
 test/qt_test/qt_test.vcxproj.filters          |  55 ++-
 test/test_ping/test_ping.cpp                  |   2 +-
 27 files changed, 1853 insertions(+), 1038 deletions(-)
 delete mode 100644 test/qt_test/jlib/qt/Ctrl/moc_ThreadCtrl.cpp
 delete mode 100644 test/qt_test/jlib/qt/View/moc_BgColorBtn.cpp
 delete mode 100644 test/qt_test/jlib/qt/View/moc_IconBtn.cpp
 delete mode 100644 test/qt_test/jlib/qt/View/moc_LoadingView.cpp
 delete mode 100644 test/qt_test/jlib/qt/View/moc_PageTitle.cpp
 delete mode 100644 test/qt_test/jlib/qt/View/moc_RndButton.cpp
 create mode 100644 test/qt_test/qt/Ctrl/ThreadCtrl.h
 create mode 100644 test/qt_test/qt/ErrorCode.h
 create mode 100644 test/qt_test/qt/Model/ThreadModel.h
 create mode 100644 test/qt_test/qt/QtDebug.h
 create mode 100644 test/qt_test/qt/QtDebugOutput.h
 create mode 100644 test/qt_test/qt/QtPathHelper.h
 create mode 100644 test/qt_test/qt/QtStylesheet.h
 create mode 100644 test/qt_test/qt/QtUtils.h
 create mode 100644 test/qt_test/qt/View/BgColorBtn.h
 create mode 100644 test/qt_test/qt/View/HttpDlg.h
 create mode 100644 test/qt_test/qt/View/HttpDlgErrorCode.h
 create mode 100644 test/qt_test/qt/View/IconBtn.h
 create mode 100644 test/qt_test/qt/View/LoadingView.h
 create mode 100644 test/qt_test/qt/View/PageTitle.h
 create mode 100644 test/qt_test/qt/View/RndButton.h
 create mode 100644 test/qt_test/qt/signal_slot.h

diff --git a/jlib/qt/View/HttpDlg.h b/jlib/qt/View/HttpDlg.h
index d6451f6..fbba6d7 100644
--- a/jlib/qt/View/HttpDlg.h
+++ b/jlib/qt/View/HttpDlg.h
@@ -14,6 +14,7 @@
 #include "../QtUtils.h"
 #include "../QtStylesheet.h"
 #include "HttpDlgErrorCode.h"
+#include "../../3rdparty/json/jsoncpp/json.h"
 
 namespace jlib
 {
@@ -21,7 +22,6 @@ namespace qt
 {
 
 
-template <typename JsonValue>
 class HttpDlg : public QDialog
 {
 	Q_OBJECT
@@ -39,22 +39,14 @@ public:
 	{
 		setWindowModality(Qt::WindowModal);
 		setWindowFlags(Qt::FramelessWindowHint);
-		if (!parent) {
-			setAttribute(Qt::WA_TranslucentBackground);
-		}
+		if (!parent) { setAttribute(Qt::WA_TranslucentBackground); }
 
-		if (sz == sz_small) {
-			setFixedSize(200, 200);
-		} else {
-			setFixedSize(630, 637);
-		}
+		if (sz == sz_small) { setFixedSize(200, 200);
+		} else { setFixedSize(630, 637); }
 
-		label_ = new QLabel(this);
-		label_->resize(width(), height());
-		label_->move(0, 0);
+		label_ = new QLabel(this); label_->resize(width(), height()); label_->move(0, 0);
 
-		elapse_ = new QLabel(this);
-		elapse_->resize(180, 80);
+		elapse_ = new QLabel(this); elapse_->resize(180, 80);
 		elapse_->move((width() - elapse_->width()) / 2, (height() - elapse_->height()) / 2);
 		elapse_->setStyleSheet(build_style(Qt::darkYellow, 64));
 		elapse_->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
@@ -65,44 +57,35 @@ public:
 		mgr = new QNetworkAccessManager(this);
 	}
 
-	~HttpDlg();
+	~HttpDlg() {}
 
 	void get(const QUrl& url) {
-		if (connection_) {
-			disconnect(connection_);
-		}
+		if (connection_) { disconnect(connection_); }
 		connection_ = connect(mgr, &QNetworkAccessManager::finished, this, &HttpDlg::onFinished);
 		reply_ = mgr->get(QNetworkRequest(url));
-
 		run();
 	}
 
 	void post(const QUrl& url) {
-		if (connection_) {
-			disconnect(connection_);
-		}
+		if (connection_) { disconnect(connection_); }
 		connection_ = connect(mgr, &QNetworkAccessManager::finished, this, &HttpDlg::onFinished);
 		QNetworkRequest request(url);
 		request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
 		reply_ = mgr->post(request, QByteArray());
-
 		run();
 	}
 
 	void post(const QNetworkRequest& request, const QByteArray& data) {
-		if (connection_) {
-			disconnect(connection_);
-		}
+		if (connection_) { disconnect(connection_); }
 		connection_ = connect(mgr, &QNetworkAccessManager::finished, this, &HttpDlg::onFinished);
 		reply_ = mgr->post(request, data);
 		run();
 	}
 
 	std::error_code get_result() const { return result_; }
+	Json::Value getRoot() const { return root_; }
 
-	JsonValue getRoot() const { return root_; }
-
-	bool getValue(const QString& name, JsonValue& value) {
+	bool getValue(const QString& name, Json::Value& value) {
 		if (root_.isMember(name.toStdString())) {
 			value = root_[name.toStdString()];
 			return true;
@@ -111,7 +94,7 @@ public:
 	}
 
 	bool getValue(const QString& name, QString& value) {
-		JsonValue val;
+		Json::Value val;
 		if (getValue(name, val)) {
 			value = QString::fromUtf8(val.asCString());
 			return true;
@@ -120,7 +103,7 @@ public:
 	}
 
 	bool getValue(const QString& name, int& value) {
-		JsonValue val;
+		Json::Value val;
 		if (getValue(name, val)) {
 			value = val.asInt();
 			return true;
@@ -156,15 +139,11 @@ protected:
 		timer_.start();
 
 		auto p = parentWidget();
-		if (p) {
-			p->setEnabled(false);
-		}
+		if (p) { p->setEnabled(false); }
 
 		startTimer(1000);
 		QDialog::exec();
-		if (p) {
-			p->setEnabled(true);
-		}
+		if (p) { p->setEnabled(true); }
 
 		movie->deleteLater();
 	}
@@ -198,13 +177,9 @@ private slots:
 			}
 
 			QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
-			if (!statusCode.isValid()) {
-				MYQDEBUG << "statusCode is not valid";
-				break;
-			}
+			if (!statusCode.isValid()) { MYQDEBUG << "statusCode is not valid"; break; }
 
 			httpStatusCode_ = statusCode.toInt();
-
 			if (httpStatusCode_ != 200) {
 				result_ = HttpDlgErrorCode::NetworkError;
 				httpReason_ = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
@@ -225,7 +200,6 @@ private slots:
 		} while (false);
 
 		QDialog::accept();
-
 		reply->deleteLater();
 	}
 
@@ -233,7 +207,7 @@ private:
 	std::error_code result_ = {};
 	int httpStatusCode_ = 0;
 	QString httpReason_ = {};
-	JsonValue root_ = {};
+	Json::Value root_ = {};
 	int time_out_sec_ = 10;
 	QNetworkAccessManager* mgr = {};
 	QNetworkReply* reply_ = {};
diff --git a/test/qt_test/jlib/qt/Ctrl/moc_ThreadCtrl.cpp b/test/qt_test/jlib/qt/Ctrl/moc_ThreadCtrl.cpp
deleted file mode 100644
index 92c264b..0000000
--- a/test/qt_test/jlib/qt/Ctrl/moc_ThreadCtrl.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/****************************************************************************
-** Meta object code from reading C++ file 'ThreadCtrl.h'
-**
-** Created by: The Qt Meta Object Compiler version 67 (Qt 5.9.8)
-**
-** WARNING! All changes made in this file will be lost!
-*****************************************************************************/
-
-#include "../../../../../jlib/qt/Ctrl/ThreadCtrl.h"
-#include <QtCore/qbytearray.h>
-#include <QtCore/qmetatype.h>
-#if !defined(Q_MOC_OUTPUT_REVISION)
-#error "The header file 'ThreadCtrl.h' doesn't include <QObject>."
-#elif Q_MOC_OUTPUT_REVISION != 67
-#error "This file was generated using the moc from 5.9.8. It"
-#error "cannot be used with the include files from this version of Qt."
-#error "(The moc has changed too much.)"
-#endif
-
-QT_BEGIN_MOC_NAMESPACE
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
-struct qt_meta_stringdata_jlib__qt__ThreadCtrl_t {
-    QByteArrayData data[9];
-    char stringdata0[106];
-};
-#define QT_MOC_LITERAL(idx, ofs, len) \
-    Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
-    qptrdiff(offsetof(qt_meta_stringdata_jlib__qt__ThreadCtrl_t, stringdata0) + ofs \
-        - idx * sizeof(QByteArrayData)) \
-    )
-static const qt_meta_stringdata_jlib__qt__ThreadCtrl_t qt_meta_stringdata_jlib__qt__ThreadCtrl = {
-    {
-QT_MOC_LITERAL(0, 0, 20), // "jlib::qt::ThreadCtrl"
-QT_MOC_LITERAL(1, 21, 9), // "sig_ready"
-QT_MOC_LITERAL(2, 31, 0), // ""
-QT_MOC_LITERAL(3, 32, 3), // "tag"
-QT_MOC_LITERAL(4, 36, 15), // "std::error_code"
-QT_MOC_LITERAL(5, 52, 6), // "result"
-QT_MOC_LITERAL(6, 59, 12), // "sig_progress"
-QT_MOC_LITERAL(7, 72, 24), // "jlib::qt::ThreadProgress"
-QT_MOC_LITERAL(8, 97, 8) // "progress"
-
-    },
-    "jlib::qt::ThreadCtrl\0sig_ready\0\0tag\0"
-    "std::error_code\0result\0sig_progress\0"
-    "jlib::qt::ThreadProgress\0progress"
-};
-#undef QT_MOC_LITERAL
-
-static const uint qt_meta_data_jlib__qt__ThreadCtrl[] = {
-
- // content:
-       7,       // revision
-       0,       // classname
-       0,    0, // classinfo
-       2,   14, // methods
-       0,    0, // properties
-       0,    0, // enums/sets
-       0,    0, // constructors
-       0,       // flags
-       2,       // signalCount
-
- // signals: name, argc, parameters, tag, flags
-       1,    2,   24,    2, 0x06 /* Public */,
-       6,    2,   29,    2, 0x06 /* Public */,
-
- // signals: parameters
-    QMetaType::Void, QMetaType::Int, 0x80000000 | 4,    3,    5,
-    QMetaType::Void, QMetaType::Int, 0x80000000 | 7,    3,    8,
-
-       0        // eod
-};
-
-void jlib::qt::ThreadCtrl::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
-{
-    if (_c == QMetaObject::InvokeMetaMethod) {
-        ThreadCtrl *_t = static_cast<ThreadCtrl *>(_o);
-        Q_UNUSED(_t)
-        switch (_id) {
-        case 0: _t->sig_ready((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< std::error_code(*)>(_a[2]))); break;
-        case 1: _t->sig_progress((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< jlib::qt::ThreadProgress(*)>(_a[2]))); break;
-        default: ;
-        }
-    } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
-        switch (_id) {
-        default: *reinterpret_cast<int*>(_a[0]) = -1; break;
-        case 0:
-            switch (*reinterpret_cast<int*>(_a[1])) {
-            default: *reinterpret_cast<int*>(_a[0]) = -1; break;
-            case 1:
-                *reinterpret_cast<int*>(_a[0]) = qRegisterMetaType< std::error_code >(); break;
-            }
-            break;
-        case 1:
-            switch (*reinterpret_cast<int*>(_a[1])) {
-            default: *reinterpret_cast<int*>(_a[0]) = -1; break;
-            case 1:
-                *reinterpret_cast<int*>(_a[0]) = qRegisterMetaType< jlib::qt::ThreadProgress >(); break;
-            }
-            break;
-        }
-    } else if (_c == QMetaObject::IndexOfMethod) {
-        int *result = reinterpret_cast<int *>(_a[0]);
-        {
-            typedef void (ThreadCtrl::*_t)(int , std::error_code );
-            if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&ThreadCtrl::sig_ready)) {
-                *result = 0;
-                return;
-            }
-        }
-        {
-            typedef void (ThreadCtrl::*_t)(int , jlib::qt::ThreadProgress );
-            if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&ThreadCtrl::sig_progress)) {
-                *result = 1;
-                return;
-            }
-        }
-    }
-}
-
-const QMetaObject jlib::qt::ThreadCtrl::staticMetaObject = {
-    { &QThread::staticMetaObject, qt_meta_stringdata_jlib__qt__ThreadCtrl.data,
-      qt_meta_data_jlib__qt__ThreadCtrl,  qt_static_metacall, nullptr, nullptr}
-};
-
-
-const QMetaObject *jlib::qt::ThreadCtrl::metaObject() const
-{
-    return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
-}
-
-void *jlib::qt::ThreadCtrl::qt_metacast(const char *_clname)
-{
-    if (!_clname) return nullptr;
-    if (!strcmp(_clname, qt_meta_stringdata_jlib__qt__ThreadCtrl.stringdata0))
-        return static_cast<void*>(this);
-    return QThread::qt_metacast(_clname);
-}
-
-int jlib::qt::ThreadCtrl::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
-{
-    _id = QThread::qt_metacall(_c, _id, _a);
-    if (_id < 0)
-        return _id;
-    if (_c == QMetaObject::InvokeMetaMethod) {
-        if (_id < 2)
-            qt_static_metacall(this, _c, _id, _a);
-        _id -= 2;
-    } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
-        if (_id < 2)
-            qt_static_metacall(this, _c, _id, _a);
-        _id -= 2;
-    }
-    return _id;
-}
-
-// SIGNAL 0
-void jlib::qt::ThreadCtrl::sig_ready(int _t1, std::error_code _t2)
-{
-    void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)) };
-    QMetaObject::activate(this, &staticMetaObject, 0, _a);
-}
-
-// SIGNAL 1
-void jlib::qt::ThreadCtrl::sig_progress(int _t1, jlib::qt::ThreadProgress _t2)
-{
-    void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)), const_cast<void*>(reinterpret_cast<const void*>(&_t2)) };
-    QMetaObject::activate(this, &staticMetaObject, 1, _a);
-}
-QT_WARNING_POP
-QT_END_MOC_NAMESPACE
diff --git a/test/qt_test/jlib/qt/View/moc_BgColorBtn.cpp b/test/qt_test/jlib/qt/View/moc_BgColorBtn.cpp
deleted file mode 100644
index 9cef2ab..0000000
--- a/test/qt_test/jlib/qt/View/moc_BgColorBtn.cpp
+++ /dev/null
@@ -1,139 +0,0 @@
-/****************************************************************************
-** Meta object code from reading C++ file 'BgColorBtn.h'
-**
-** Created by: The Qt Meta Object Compiler version 67 (Qt 5.9.8)
-**
-** WARNING! All changes made in this file will be lost!
-*****************************************************************************/
-
-#include "../../../../../jlib/qt/View/BgColorBtn.h"
-#include <QtCore/qbytearray.h>
-#include <QtCore/qmetatype.h>
-#if !defined(Q_MOC_OUTPUT_REVISION)
-#error "The header file 'BgColorBtn.h' doesn't include <QObject>."
-#elif Q_MOC_OUTPUT_REVISION != 67
-#error "This file was generated using the moc from 5.9.8. It"
-#error "cannot be used with the include files from this version of Qt."
-#error "(The moc has changed too much.)"
-#endif
-
-QT_BEGIN_MOC_NAMESPACE
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
-struct qt_meta_stringdata_jlib__qt__BgColorBtn_t {
-    QByteArrayData data[5];
-    char stringdata0[51];
-};
-#define QT_MOC_LITERAL(idx, ofs, len) \
-    Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
-    qptrdiff(offsetof(qt_meta_stringdata_jlib__qt__BgColorBtn_t, stringdata0) + ofs \
-        - idx * sizeof(QByteArrayData)) \
-    )
-static const qt_meta_stringdata_jlib__qt__BgColorBtn_t qt_meta_stringdata_jlib__qt__BgColorBtn = {
-    {
-QT_MOC_LITERAL(0, 0, 20), // "jlib::qt::BgColorBtn"
-QT_MOC_LITERAL(1, 21, 11), // "sig_clicked"
-QT_MOC_LITERAL(2, 33, 0), // ""
-QT_MOC_LITERAL(3, 34, 3), // "tag"
-QT_MOC_LITERAL(4, 38, 12) // "slot_clicked"
-
-    },
-    "jlib::qt::BgColorBtn\0sig_clicked\0\0tag\0"
-    "slot_clicked"
-};
-#undef QT_MOC_LITERAL
-
-static const uint qt_meta_data_jlib__qt__BgColorBtn[] = {
-
- // content:
-       7,       // revision
-       0,       // classname
-       0,    0, // classinfo
-       2,   14, // methods
-       0,    0, // properties
-       0,    0, // enums/sets
-       0,    0, // constructors
-       0,       // flags
-       1,       // signalCount
-
- // signals: name, argc, parameters, tag, flags
-       1,    1,   24,    2, 0x06 /* Public */,
-
- // slots: name, argc, parameters, tag, flags
-       4,    0,   27,    2, 0x08 /* Private */,
-
- // signals: parameters
-    QMetaType::Void, QMetaType::Int,    3,
-
- // slots: parameters
-    QMetaType::Void,
-
-       0        // eod
-};
-
-void jlib::qt::BgColorBtn::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
-{
-    if (_c == QMetaObject::InvokeMetaMethod) {
-        BgColorBtn *_t = static_cast<BgColorBtn *>(_o);
-        Q_UNUSED(_t)
-        switch (_id) {
-        case 0: _t->sig_clicked((*reinterpret_cast< int(*)>(_a[1]))); break;
-        case 1: _t->slot_clicked(); break;
-        default: ;
-        }
-    } else if (_c == QMetaObject::IndexOfMethod) {
-        int *result = reinterpret_cast<int *>(_a[0]);
-        {
-            typedef void (BgColorBtn::*_t)(int );
-            if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&BgColorBtn::sig_clicked)) {
-                *result = 0;
-                return;
-            }
-        }
-    }
-}
-
-const QMetaObject jlib::qt::BgColorBtn::staticMetaObject = {
-    { &QPushButton::staticMetaObject, qt_meta_stringdata_jlib__qt__BgColorBtn.data,
-      qt_meta_data_jlib__qt__BgColorBtn,  qt_static_metacall, nullptr, nullptr}
-};
-
-
-const QMetaObject *jlib::qt::BgColorBtn::metaObject() const
-{
-    return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
-}
-
-void *jlib::qt::BgColorBtn::qt_metacast(const char *_clname)
-{
-    if (!_clname) return nullptr;
-    if (!strcmp(_clname, qt_meta_stringdata_jlib__qt__BgColorBtn.stringdata0))
-        return static_cast<void*>(this);
-    return QPushButton::qt_metacast(_clname);
-}
-
-int jlib::qt::BgColorBtn::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
-{
-    _id = QPushButton::qt_metacall(_c, _id, _a);
-    if (_id < 0)
-        return _id;
-    if (_c == QMetaObject::InvokeMetaMethod) {
-        if (_id < 2)
-            qt_static_metacall(this, _c, _id, _a);
-        _id -= 2;
-    } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
-        if (_id < 2)
-            *reinterpret_cast<int*>(_a[0]) = -1;
-        _id -= 2;
-    }
-    return _id;
-}
-
-// SIGNAL 0
-void jlib::qt::BgColorBtn::sig_clicked(int _t1)
-{
-    void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
-    QMetaObject::activate(this, &staticMetaObject, 0, _a);
-}
-QT_WARNING_POP
-QT_END_MOC_NAMESPACE
diff --git a/test/qt_test/jlib/qt/View/moc_IconBtn.cpp b/test/qt_test/jlib/qt/View/moc_IconBtn.cpp
deleted file mode 100644
index a526333..0000000
--- a/test/qt_test/jlib/qt/View/moc_IconBtn.cpp
+++ /dev/null
@@ -1,191 +0,0 @@
-/****************************************************************************
-** Meta object code from reading C++ file 'IconBtn.h'
-**
-** Created by: The Qt Meta Object Compiler version 67 (Qt 5.9.8)
-**
-** WARNING! All changes made in this file will be lost!
-*****************************************************************************/
-
-#include "../../../../../jlib/qt/View/IconBtn.h"
-#include <QtCore/qbytearray.h>
-#include <QtCore/qmetatype.h>
-#if !defined(Q_MOC_OUTPUT_REVISION)
-#error "The header file 'IconBtn.h' doesn't include <QObject>."
-#elif Q_MOC_OUTPUT_REVISION != 67
-#error "This file was generated using the moc from 5.9.8. It"
-#error "cannot be used with the include files from this version of Qt."
-#error "(The moc has changed too much.)"
-#endif
-
-QT_BEGIN_MOC_NAMESPACE
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
-struct qt_meta_stringdata_jlib__qt__IconBtn_t {
-    QByteArrayData data[8];
-    char stringdata0[111];
-};
-#define QT_MOC_LITERAL(idx, ofs, len) \
-    Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
-    qptrdiff(offsetof(qt_meta_stringdata_jlib__qt__IconBtn_t, stringdata0) + ofs \
-        - idx * sizeof(QByteArrayData)) \
-    )
-static const qt_meta_stringdata_jlib__qt__IconBtn_t qt_meta_stringdata_jlib__qt__IconBtn = {
-    {
-QT_MOC_LITERAL(0, 0, 17), // "jlib::qt::IconBtn"
-QT_MOC_LITERAL(1, 18, 7), // "clicked"
-QT_MOC_LITERAL(2, 26, 0), // ""
-QT_MOC_LITERAL(3, 27, 18), // "long_press_trigger"
-QT_MOC_LITERAL(4, 46, 8), // "is_press"
-QT_MOC_LITERAL(5, 55, 15), // "sig_mouse_enter"
-QT_MOC_LITERAL(6, 71, 15), // "sig_mouse_leave"
-QT_MOC_LITERAL(7, 87, 23) // "slot_long_press_timeout"
-
-    },
-    "jlib::qt::IconBtn\0clicked\0\0"
-    "long_press_trigger\0is_press\0sig_mouse_enter\0"
-    "sig_mouse_leave\0slot_long_press_timeout"
-};
-#undef QT_MOC_LITERAL
-
-static const uint qt_meta_data_jlib__qt__IconBtn[] = {
-
- // content:
-       7,       // revision
-       0,       // classname
-       0,    0, // classinfo
-       5,   14, // methods
-       0,    0, // properties
-       0,    0, // enums/sets
-       0,    0, // constructors
-       0,       // flags
-       4,       // signalCount
-
- // signals: name, argc, parameters, tag, flags
-       1,    0,   39,    2, 0x06 /* Public */,
-       3,    1,   40,    2, 0x06 /* Public */,
-       5,    0,   43,    2, 0x06 /* Public */,
-       6,    0,   44,    2, 0x06 /* Public */,
-
- // slots: name, argc, parameters, tag, flags
-       7,    0,   45,    2, 0x08 /* Private */,
-
- // signals: parameters
-    QMetaType::Void,
-    QMetaType::Void, QMetaType::Bool,    4,
-    QMetaType::Void,
-    QMetaType::Void,
-
- // slots: parameters
-    QMetaType::Void,
-
-       0        // eod
-};
-
-void jlib::qt::IconBtn::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
-{
-    if (_c == QMetaObject::InvokeMetaMethod) {
-        IconBtn *_t = static_cast<IconBtn *>(_o);
-        Q_UNUSED(_t)
-        switch (_id) {
-        case 0: _t->clicked(); break;
-        case 1: _t->long_press_trigger((*reinterpret_cast< bool(*)>(_a[1]))); break;
-        case 2: _t->sig_mouse_enter(); break;
-        case 3: _t->sig_mouse_leave(); break;
-        case 4: _t->slot_long_press_timeout(); break;
-        default: ;
-        }
-    } else if (_c == QMetaObject::IndexOfMethod) {
-        int *result = reinterpret_cast<int *>(_a[0]);
-        {
-            typedef void (IconBtn::*_t)();
-            if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&IconBtn::clicked)) {
-                *result = 0;
-                return;
-            }
-        }
-        {
-            typedef void (IconBtn::*_t)(bool );
-            if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&IconBtn::long_press_trigger)) {
-                *result = 1;
-                return;
-            }
-        }
-        {
-            typedef void (IconBtn::*_t)();
-            if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&IconBtn::sig_mouse_enter)) {
-                *result = 2;
-                return;
-            }
-        }
-        {
-            typedef void (IconBtn::*_t)();
-            if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&IconBtn::sig_mouse_leave)) {
-                *result = 3;
-                return;
-            }
-        }
-    }
-}
-
-const QMetaObject jlib::qt::IconBtn::staticMetaObject = {
-    { &QLabel::staticMetaObject, qt_meta_stringdata_jlib__qt__IconBtn.data,
-      qt_meta_data_jlib__qt__IconBtn,  qt_static_metacall, nullptr, nullptr}
-};
-
-
-const QMetaObject *jlib::qt::IconBtn::metaObject() const
-{
-    return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
-}
-
-void *jlib::qt::IconBtn::qt_metacast(const char *_clname)
-{
-    if (!_clname) return nullptr;
-    if (!strcmp(_clname, qt_meta_stringdata_jlib__qt__IconBtn.stringdata0))
-        return static_cast<void*>(this);
-    return QLabel::qt_metacast(_clname);
-}
-
-int jlib::qt::IconBtn::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
-{
-    _id = QLabel::qt_metacall(_c, _id, _a);
-    if (_id < 0)
-        return _id;
-    if (_c == QMetaObject::InvokeMetaMethod) {
-        if (_id < 5)
-            qt_static_metacall(this, _c, _id, _a);
-        _id -= 5;
-    } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
-        if (_id < 5)
-            *reinterpret_cast<int*>(_a[0]) = -1;
-        _id -= 5;
-    }
-    return _id;
-}
-
-// SIGNAL 0
-void jlib::qt::IconBtn::clicked()
-{
-    QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
-}
-
-// SIGNAL 1
-void jlib::qt::IconBtn::long_press_trigger(bool _t1)
-{
-    void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
-    QMetaObject::activate(this, &staticMetaObject, 1, _a);
-}
-
-// SIGNAL 2
-void jlib::qt::IconBtn::sig_mouse_enter()
-{
-    QMetaObject::activate(this, &staticMetaObject, 2, nullptr);
-}
-
-// SIGNAL 3
-void jlib::qt::IconBtn::sig_mouse_leave()
-{
-    QMetaObject::activate(this, &staticMetaObject, 3, nullptr);
-}
-QT_WARNING_POP
-QT_END_MOC_NAMESPACE
diff --git a/test/qt_test/jlib/qt/View/moc_LoadingView.cpp b/test/qt_test/jlib/qt/View/moc_LoadingView.cpp
deleted file mode 100644
index 59b28e1..0000000
--- a/test/qt_test/jlib/qt/View/moc_LoadingView.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-/****************************************************************************
-** Meta object code from reading C++ file 'LoadingView.h'
-**
-** Created by: The Qt Meta Object Compiler version 67 (Qt 5.9.8)
-**
-** WARNING! All changes made in this file will be lost!
-*****************************************************************************/
-
-#include "../../../../../jlib/qt/View/LoadingView.h"
-#include <QtCore/qbytearray.h>
-#include <QtCore/qmetatype.h>
-#if !defined(Q_MOC_OUTPUT_REVISION)
-#error "The header file 'LoadingView.h' doesn't include <QObject>."
-#elif Q_MOC_OUTPUT_REVISION != 67
-#error "This file was generated using the moc from 5.9.8. It"
-#error "cannot be used with the include files from this version of Qt."
-#error "(The moc has changed too much.)"
-#endif
-
-QT_BEGIN_MOC_NAMESPACE
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
-struct qt_meta_stringdata_jlib__qt__LoadingView_t {
-    QByteArrayData data[9];
-    char stringdata0[105];
-};
-#define QT_MOC_LITERAL(idx, ofs, len) \
-    Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
-    qptrdiff(offsetof(qt_meta_stringdata_jlib__qt__LoadingView_t, stringdata0) + ofs \
-        - idx * sizeof(QByteArrayData)) \
-    )
-static const qt_meta_stringdata_jlib__qt__LoadingView_t qt_meta_stringdata_jlib__qt__LoadingView = {
-    {
-QT_MOC_LITERAL(0, 0, 21), // "jlib::qt::LoadingView"
-QT_MOC_LITERAL(1, 22, 10), // "slot_ready"
-QT_MOC_LITERAL(2, 33, 0), // ""
-QT_MOC_LITERAL(3, 34, 3), // "tag"
-QT_MOC_LITERAL(4, 38, 15), // "std::error_code"
-QT_MOC_LITERAL(5, 54, 2), // "ec"
-QT_MOC_LITERAL(6, 57, 13), // "slot_progress"
-QT_MOC_LITERAL(7, 71, 24), // "jlib::qt::ThreadProgress"
-QT_MOC_LITERAL(8, 96, 8) // "progress"
-
-    },
-    "jlib::qt::LoadingView\0slot_ready\0\0tag\0"
-    "std::error_code\0ec\0slot_progress\0"
-    "jlib::qt::ThreadProgress\0progress"
-};
-#undef QT_MOC_LITERAL
-
-static const uint qt_meta_data_jlib__qt__LoadingView[] = {
-
- // content:
-       7,       // revision
-       0,       // classname
-       0,    0, // classinfo
-       2,   14, // methods
-       0,    0, // properties
-       0,    0, // enums/sets
-       0,    0, // constructors
-       0,       // flags
-       0,       // signalCount
-
- // slots: name, argc, parameters, tag, flags
-       1,    2,   24,    2, 0x08 /* Private */,
-       6,    2,   29,    2, 0x08 /* Private */,
-
- // slots: parameters
-    QMetaType::Void, QMetaType::Int, 0x80000000 | 4,    3,    5,
-    QMetaType::Void, QMetaType::Int, 0x80000000 | 7,    3,    8,
-
-       0        // eod
-};
-
-void jlib::qt::LoadingView::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
-{
-    if (_c == QMetaObject::InvokeMetaMethod) {
-        LoadingView *_t = static_cast<LoadingView *>(_o);
-        Q_UNUSED(_t)
-        switch (_id) {
-        case 0: _t->slot_ready((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< std::error_code(*)>(_a[2]))); break;
-        case 1: _t->slot_progress((*reinterpret_cast< int(*)>(_a[1])),(*reinterpret_cast< jlib::qt::ThreadProgress(*)>(_a[2]))); break;
-        default: ;
-        }
-    } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
-        switch (_id) {
-        default: *reinterpret_cast<int*>(_a[0]) = -1; break;
-        case 0:
-            switch (*reinterpret_cast<int*>(_a[1])) {
-            default: *reinterpret_cast<int*>(_a[0]) = -1; break;
-            case 1:
-                *reinterpret_cast<int*>(_a[0]) = qRegisterMetaType< std::error_code >(); break;
-            }
-            break;
-        case 1:
-            switch (*reinterpret_cast<int*>(_a[1])) {
-            default: *reinterpret_cast<int*>(_a[0]) = -1; break;
-            case 1:
-                *reinterpret_cast<int*>(_a[0]) = qRegisterMetaType< jlib::qt::ThreadProgress >(); break;
-            }
-            break;
-        }
-    }
-}
-
-const QMetaObject jlib::qt::LoadingView::staticMetaObject = {
-    { &QDialog::staticMetaObject, qt_meta_stringdata_jlib__qt__LoadingView.data,
-      qt_meta_data_jlib__qt__LoadingView,  qt_static_metacall, nullptr, nullptr}
-};
-
-
-const QMetaObject *jlib::qt::LoadingView::metaObject() const
-{
-    return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
-}
-
-void *jlib::qt::LoadingView::qt_metacast(const char *_clname)
-{
-    if (!_clname) return nullptr;
-    if (!strcmp(_clname, qt_meta_stringdata_jlib__qt__LoadingView.stringdata0))
-        return static_cast<void*>(this);
-    return QDialog::qt_metacast(_clname);
-}
-
-int jlib::qt::LoadingView::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
-{
-    _id = QDialog::qt_metacall(_c, _id, _a);
-    if (_id < 0)
-        return _id;
-    if (_c == QMetaObject::InvokeMetaMethod) {
-        if (_id < 2)
-            qt_static_metacall(this, _c, _id, _a);
-        _id -= 2;
-    } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
-        if (_id < 2)
-            qt_static_metacall(this, _c, _id, _a);
-        _id -= 2;
-    }
-    return _id;
-}
-QT_WARNING_POP
-QT_END_MOC_NAMESPACE
diff --git a/test/qt_test/jlib/qt/View/moc_PageTitle.cpp b/test/qt_test/jlib/qt/View/moc_PageTitle.cpp
deleted file mode 100644
index 5c893d2..0000000
--- a/test/qt_test/jlib/qt/View/moc_PageTitle.cpp
+++ /dev/null
@@ -1,165 +0,0 @@
-/****************************************************************************
-** Meta object code from reading C++ file 'PageTitle.h'
-**
-** Created by: The Qt Meta Object Compiler version 67 (Qt 5.9.8)
-**
-** WARNING! All changes made in this file will be lost!
-*****************************************************************************/
-
-#include "../../../../../jlib/qt/View/PageTitle.h"
-#include <QtCore/qbytearray.h>
-#include <QtCore/qmetatype.h>
-#if !defined(Q_MOC_OUTPUT_REVISION)
-#error "The header file 'PageTitle.h' doesn't include <QObject>."
-#elif Q_MOC_OUTPUT_REVISION != 67
-#error "This file was generated using the moc from 5.9.8. It"
-#error "cannot be used with the include files from this version of Qt."
-#error "(The moc has changed too much.)"
-#endif
-
-QT_BEGIN_MOC_NAMESPACE
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
-struct qt_meta_stringdata_jlib__qt__PageTitle_t {
-    QByteArrayData data[8];
-    char stringdata0[101];
-};
-#define QT_MOC_LITERAL(idx, ofs, len) \
-    Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
-    qptrdiff(offsetof(qt_meta_stringdata_jlib__qt__PageTitle_t, stringdata0) + ofs \
-        - idx * sizeof(QByteArrayData)) \
-    )
-static const qt_meta_stringdata_jlib__qt__PageTitle_t qt_meta_stringdata_jlib__qt__PageTitle = {
-    {
-QT_MOC_LITERAL(0, 0, 19), // "jlib::qt::PageTitle"
-QT_MOC_LITERAL(1, 20, 9), // "sig_close"
-QT_MOC_LITERAL(2, 30, 0), // ""
-QT_MOC_LITERAL(3, 31, 13), // "sig_maximized"
-QT_MOC_LITERAL(4, 45, 5), // "isMax"
-QT_MOC_LITERAL(5, 51, 13), // "slot_minimize"
-QT_MOC_LITERAL(6, 65, 24), // "slot_maximize_or_restore"
-QT_MOC_LITERAL(7, 90, 10) // "slot_close"
-
-    },
-    "jlib::qt::PageTitle\0sig_close\0\0"
-    "sig_maximized\0isMax\0slot_minimize\0"
-    "slot_maximize_or_restore\0slot_close"
-};
-#undef QT_MOC_LITERAL
-
-static const uint qt_meta_data_jlib__qt__PageTitle[] = {
-
- // content:
-       7,       // revision
-       0,       // classname
-       0,    0, // classinfo
-       5,   14, // methods
-       0,    0, // properties
-       0,    0, // enums/sets
-       0,    0, // constructors
-       0,       // flags
-       2,       // signalCount
-
- // signals: name, argc, parameters, tag, flags
-       1,    0,   39,    2, 0x06 /* Public */,
-       3,    1,   40,    2, 0x06 /* Public */,
-
- // slots: name, argc, parameters, tag, flags
-       5,    0,   43,    2, 0x08 /* Private */,
-       6,    0,   44,    2, 0x08 /* Private */,
-       7,    0,   45,    2, 0x08 /* Private */,
-
- // signals: parameters
-    QMetaType::Void,
-    QMetaType::Void, QMetaType::Bool,    4,
-
- // slots: parameters
-    QMetaType::Void,
-    QMetaType::Void,
-    QMetaType::Void,
-
-       0        // eod
-};
-
-void jlib::qt::PageTitle::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
-{
-    if (_c == QMetaObject::InvokeMetaMethod) {
-        PageTitle *_t = static_cast<PageTitle *>(_o);
-        Q_UNUSED(_t)
-        switch (_id) {
-        case 0: _t->sig_close(); break;
-        case 1: _t->sig_maximized((*reinterpret_cast< bool(*)>(_a[1]))); break;
-        case 2: _t->slot_minimize(); break;
-        case 3: _t->slot_maximize_or_restore(); break;
-        case 4: _t->slot_close(); break;
-        default: ;
-        }
-    } else if (_c == QMetaObject::IndexOfMethod) {
-        int *result = reinterpret_cast<int *>(_a[0]);
-        {
-            typedef void (PageTitle::*_t)();
-            if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&PageTitle::sig_close)) {
-                *result = 0;
-                return;
-            }
-        }
-        {
-            typedef void (PageTitle::*_t)(bool );
-            if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&PageTitle::sig_maximized)) {
-                *result = 1;
-                return;
-            }
-        }
-    }
-}
-
-const QMetaObject jlib::qt::PageTitle::staticMetaObject = {
-    { &QWidget::staticMetaObject, qt_meta_stringdata_jlib__qt__PageTitle.data,
-      qt_meta_data_jlib__qt__PageTitle,  qt_static_metacall, nullptr, nullptr}
-};
-
-
-const QMetaObject *jlib::qt::PageTitle::metaObject() const
-{
-    return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
-}
-
-void *jlib::qt::PageTitle::qt_metacast(const char *_clname)
-{
-    if (!_clname) return nullptr;
-    if (!strcmp(_clname, qt_meta_stringdata_jlib__qt__PageTitle.stringdata0))
-        return static_cast<void*>(this);
-    return QWidget::qt_metacast(_clname);
-}
-
-int jlib::qt::PageTitle::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
-{
-    _id = QWidget::qt_metacall(_c, _id, _a);
-    if (_id < 0)
-        return _id;
-    if (_c == QMetaObject::InvokeMetaMethod) {
-        if (_id < 5)
-            qt_static_metacall(this, _c, _id, _a);
-        _id -= 5;
-    } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
-        if (_id < 5)
-            *reinterpret_cast<int*>(_a[0]) = -1;
-        _id -= 5;
-    }
-    return _id;
-}
-
-// SIGNAL 0
-void jlib::qt::PageTitle::sig_close()
-{
-    QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
-}
-
-// SIGNAL 1
-void jlib::qt::PageTitle::sig_maximized(bool _t1)
-{
-    void *_a[] = { nullptr, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
-    QMetaObject::activate(this, &staticMetaObject, 1, _a);
-}
-QT_WARNING_POP
-QT_END_MOC_NAMESPACE
diff --git a/test/qt_test/jlib/qt/View/moc_RndButton.cpp b/test/qt_test/jlib/qt/View/moc_RndButton.cpp
deleted file mode 100644
index 47c33a3..0000000
--- a/test/qt_test/jlib/qt/View/moc_RndButton.cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-/****************************************************************************
-** Meta object code from reading C++ file 'RndButton.h'
-**
-** Created by: The Qt Meta Object Compiler version 67 (Qt 5.9.8)
-**
-** WARNING! All changes made in this file will be lost!
-*****************************************************************************/
-
-#include "../../../../../jlib/qt/View/RndButton.h"
-#include <QtCore/qbytearray.h>
-#include <QtCore/qmetatype.h>
-#if !defined(Q_MOC_OUTPUT_REVISION)
-#error "The header file 'RndButton.h' doesn't include <QObject>."
-#elif Q_MOC_OUTPUT_REVISION != 67
-#error "This file was generated using the moc from 5.9.8. It"
-#error "cannot be used with the include files from this version of Qt."
-#error "(The moc has changed too much.)"
-#endif
-
-QT_BEGIN_MOC_NAMESPACE
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_DEPRECATED
-struct qt_meta_stringdata_jlib__qt__RndButton_t {
-    QByteArrayData data[3];
-    char stringdata0[29];
-};
-#define QT_MOC_LITERAL(idx, ofs, len) \
-    Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \
-    qptrdiff(offsetof(qt_meta_stringdata_jlib__qt__RndButton_t, stringdata0) + ofs \
-        - idx * sizeof(QByteArrayData)) \
-    )
-static const qt_meta_stringdata_jlib__qt__RndButton_t qt_meta_stringdata_jlib__qt__RndButton = {
-    {
-QT_MOC_LITERAL(0, 0, 19), // "jlib::qt::RndButton"
-QT_MOC_LITERAL(1, 20, 7), // "clicked"
-QT_MOC_LITERAL(2, 28, 0) // ""
-
-    },
-    "jlib::qt::RndButton\0clicked\0"
-};
-#undef QT_MOC_LITERAL
-
-static const uint qt_meta_data_jlib__qt__RndButton[] = {
-
- // content:
-       7,       // revision
-       0,       // classname
-       0,    0, // classinfo
-       1,   14, // methods
-       0,    0, // properties
-       0,    0, // enums/sets
-       0,    0, // constructors
-       0,       // flags
-       1,       // signalCount
-
- // signals: name, argc, parameters, tag, flags
-       1,    0,   19,    2, 0x06 /* Public */,
-
- // signals: parameters
-    QMetaType::Void,
-
-       0        // eod
-};
-
-void jlib::qt::RndButton::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
-{
-    if (_c == QMetaObject::InvokeMetaMethod) {
-        RndButton *_t = static_cast<RndButton *>(_o);
-        Q_UNUSED(_t)
-        switch (_id) {
-        case 0: _t->clicked(); break;
-        default: ;
-        }
-    } else if (_c == QMetaObject::IndexOfMethod) {
-        int *result = reinterpret_cast<int *>(_a[0]);
-        {
-            typedef void (RndButton::*_t)();
-            if (*reinterpret_cast<_t *>(_a[1]) == static_cast<_t>(&RndButton::clicked)) {
-                *result = 0;
-                return;
-            }
-        }
-    }
-    Q_UNUSED(_a);
-}
-
-const QMetaObject jlib::qt::RndButton::staticMetaObject = {
-    { &QWidget::staticMetaObject, qt_meta_stringdata_jlib__qt__RndButton.data,
-      qt_meta_data_jlib__qt__RndButton,  qt_static_metacall, nullptr, nullptr}
-};
-
-
-const QMetaObject *jlib::qt::RndButton::metaObject() const
-{
-    return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;
-}
-
-void *jlib::qt::RndButton::qt_metacast(const char *_clname)
-{
-    if (!_clname) return nullptr;
-    if (!strcmp(_clname, qt_meta_stringdata_jlib__qt__RndButton.stringdata0))
-        return static_cast<void*>(this);
-    return QWidget::qt_metacast(_clname);
-}
-
-int jlib::qt::RndButton::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
-{
-    _id = QWidget::qt_metacall(_c, _id, _a);
-    if (_id < 0)
-        return _id;
-    if (_c == QMetaObject::InvokeMetaMethod) {
-        if (_id < 1)
-            qt_static_metacall(this, _c, _id, _a);
-        _id -= 1;
-    } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) {
-        if (_id < 1)
-            *reinterpret_cast<int*>(_a[0]) = -1;
-        _id -= 1;
-    }
-    return _id;
-}
-
-// SIGNAL 0
-void jlib::qt::RndButton::clicked()
-{
-    QMetaObject::activate(this, &staticMetaObject, 0, nullptr);
-}
-QT_WARNING_POP
-QT_END_MOC_NAMESPACE
diff --git a/test/qt_test/qt/Ctrl/ThreadCtrl.h b/test/qt_test/qt/Ctrl/ThreadCtrl.h
new file mode 100644
index 0000000..3069022
--- /dev/null
+++ b/test/qt_test/qt/Ctrl/ThreadCtrl.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <QThread>
+#include "../Model/ThreadModel.h"
+#include <thread>
+
+namespace jlib
+{
+namespace qt
+{
+
+
+class ThreadCtrl : public QThread
+{
+	Q_OBJECT
+
+public:
+	ThreadCtrl(QObject *parent, ThreadWorker worker)
+		: QThread(parent)
+		, worker_(worker)
+	{
+	}
+
+	~ThreadCtrl() {}
+
+	void set_worker(ThreadWorker worker) { worker_ = worker; }
+
+	void set_tag(int tag) { tag_ = tag; }
+	int get_tag() const { return tag_; }
+
+protected:
+	virtual void run() override {
+		std::error_code result;
+
+		if (worker_) {
+			result = worker_();
+		}
+
+		emit sig_ready(tag_, result);
+	}
+
+signals:
+	void sig_ready(int tag, std::error_code result);
+	void sig_progress(int tag, jlib::qt::ThreadProgress progress);
+
+private:
+	ThreadWorker worker_ = {};
+
+	void* input_ = nullptr;
+	void* output_ = nullptr;
+
+	int tag_ = 0;
+};
+
+}
+}
diff --git a/test/qt_test/qt/ErrorCode.h b/test/qt_test/qt/ErrorCode.h
new file mode 100644
index 0000000..d0f4719
--- /dev/null
+++ b/test/qt_test/qt/ErrorCode.h
@@ -0,0 +1,84 @@
+#pragma once
+
+#include <system_error>
+#include <QString>
+
+
+namespace jlib
+{
+namespace qt
+{
+
+
+//! »ñÈ¡´íÎóÂëÎÄ×ÖÃèÊö
+inline QString ecString(const std::error_code& ec) {
+	return QString::fromLocal8Bit(ec.message().data());
+}
+
+//! »ñÈ¡´íÎóÂëÎÄ×ÖÃèÊö£¨´øÓдíÎóĿ¼£©
+inline QString ecStringWithCategory(const std::error_code& ec) {
+	return QString::fromLocal8Bit(ec.category().name()) + ": " + QString::fromLocal8Bit(ec.message().data());
+}
+
+#define BREAK_IF_QUERY_FAILED(ec_type) if (!ok) { \
+	ec = ec_type; \
+	MYQCRITICAL << ecStringWithCategory(ec) << "\n" << query.lastError(); \
+	break; \
+}
+
+enum class CommonErrorCode {
+	OpenDbFailed = 1,
+	CreateDbTableFailed,
+	QueryDbFailed,
+
+};
+
+}
+}
+
+namespace std
+{
+
+#define ENABLE_ENUM_AS_ERROR_CODE(type) \
+template <> struct is_error_code_enum<type> : true_type {}; \
+std::error_code make_error_code(type);
+
+
+ENABLE_ENUM_AS_ERROR_CODE(jlib::qt::CommonErrorCode)
+
+}
+
+namespace
+{
+
+struct CommonErrorCatagory : public std::error_category
+{
+	const char* name() const noexcept override {
+		return "Common Error";
+	}
+
+	std::string message(int ev) const override {
+		switch (static_cast<jlib::qt::CommonErrorCode>(ev)) {
+			case jlib::qt::CommonErrorCode::OpenDbFailed:
+				return QObject::tr("Failed to open database").toLocal8Bit().toStdString();
+			case jlib::qt::CommonErrorCode::CreateDbTableFailed:
+				return QObject::tr("Failed to create table").toLocal8Bit().toStdString();
+			case jlib::qt::CommonErrorCode::QueryDbFailed:
+				return QObject::tr("Failed to query database").toLocal8Bit().toStdString();
+			default:
+				return QObject::tr("Unkown Error").toLocal8Bit().toStdString();
+		}
+	}
+};
+
+static const CommonErrorCatagory theCommonErrorCatagory = {};
+
+}
+
+inline std::error_code std::make_error_code(jlib::qt::CommonErrorCode ec)
+{
+	return { static_cast<int>(ec), theCommonErrorCatagory };
+}
+
+
+
diff --git a/test/qt_test/qt/Model/ThreadModel.h b/test/qt_test/qt/Model/ThreadModel.h
new file mode 100644
index 0000000..c50f25a
--- /dev/null
+++ b/test/qt_test/qt/Model/ThreadModel.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <QString>
+#include <functional>
+
+namespace jlib
+{
+namespace qt
+{
+
+
+typedef std::function<std::error_code(void)> ThreadWorker;
+
+struct ThreadProgress {
+	int pos = 0;
+	int total = 0;
+
+	ThreadProgress() {}
+	ThreadProgress(int p, int t) :pos(p), total(t) {}
+};
+
+typedef std::function<void(ThreadProgress)> ThreadProgressCB;
+
+}
+}
+
+Q_DECLARE_METATYPE(std::error_code)
+Q_DECLARE_METATYPE(jlib::qt::ThreadProgress)
diff --git a/test/qt_test/qt/QtDebug.h b/test/qt_test/qt/QtDebug.h
new file mode 100644
index 0000000..b1ea7b8
--- /dev/null
+++ b/test/qt_test/qt/QtDebug.h
@@ -0,0 +1,14 @@
+#pragma once
+
+#include <QDebug>
+#ifdef _WIN32
+#include <Windows.h>
+#endif //_WIN32
+
+
+#define QDEBUG_FILE_LINE_STREAM "[" << __FUNCTION__ << "ln" << __LINE__ << "]: "
+#define QDEBUG_FILE_LINE_VER (QString("[") + __FUNCTION__ + " ln" + QString::number(__LINE__) + "]: ")
+
+#define MYQDEBUG qDebug() << QDEBUG_FILE_LINE_STREAM
+#define MYQWARN qWarning() << QDEBUG_FILE_LINE_STREAM
+#define MYQCRITICAL qCritical() << QDEBUG_FILE_LINE_STREAM
\ No newline at end of file
diff --git a/test/qt_test/qt/QtDebugOutput.h b/test/qt_test/qt/QtDebugOutput.h
new file mode 100644
index 0000000..16bd88f
--- /dev/null
+++ b/test/qt_test/qt/QtDebugOutput.h
@@ -0,0 +1,41 @@
+#pragma once
+
+
+// if not defined, disable redirect
+// if defined, you must include log2.h before include this file
+#define REDIRECT_QT_OUTPUT_TO_LOG
+
+
+#ifdef REDIRECT_QT_OUTPUT_TO_LOG
+#ifndef JLIB_LOG2_ENABLED
+#error 'You must include <jlib/log2.h> first!'
+#else // has JLIB_LOG2_ENABLED
+static inline void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+{
+	using namespace jlib;
+	QByteArray localMsg = msg.toLocal8Bit();
+	switch (type) {
+	case QtDebugMsg:
+		JLOG_INFO(localMsg.data());
+		break;
+	case QtWarningMsg:
+		if (!msg.contains("libpng")) {
+			JLOG_WARN(localMsg.data());
+		}
+		break;
+	case QtCriticalMsg:
+		JLOG_CRTC(localMsg.data());
+		break;
+	case QtFatalMsg:
+		JLOG_ERRO(localMsg.data());
+		break;
+	case QtInfoMsg:
+		JLOG_INFO(localMsg.data());
+		break;
+	default:
+		JLOG_WARN(localMsg.data());
+		break;
+	}
+}
+#endif // JLIB_LOG2_ENABLED
+#endif // REDIRECT_QT_OUTPUT_TO_LOG
diff --git a/test/qt_test/qt/QtPathHelper.h b/test/qt_test/qt/QtPathHelper.h
new file mode 100644
index 0000000..e618f42
--- /dev/null
+++ b/test/qt_test/qt/QtPathHelper.h
@@ -0,0 +1,84 @@
+#pragma once
+#include <QDir>
+#include <QCoreApplication>
+#include <QString>
+#include <QDateTime>
+
+namespace jlib {
+namespace qt {
+
+static const auto FILE_TIME_FORMAT = "yyyy-MM-dd_hh-mm-ss";
+
+struct PathHelper 
+{
+	static inline bool mkpath(const QString& path) {
+		QDir dir;
+		return dir.exists(path) ? true : dir.mkpath(path);
+	}
+
+	static inline QString program() {
+		struct Helper {
+			Helper() {
+				QDir dir(QCoreApplication::applicationDirPath());
+				dir.cdUp();
+				path = dir.absolutePath();
+			}
+
+			QString path = {};
+		};
+		
+		static Helper helper;
+		return helper.path;
+	}
+
+	static inline QString bin() {
+		return program() + "/bin";
+	}
+	
+	static inline QString log() {
+		return program() + "/log";
+	}
+
+	static inline QString sdk() {
+		return program() + "/sdks";
+	}
+
+	static inline QString data() {
+		return program() + "/data";
+	}
+
+	static inline QString config() {
+		return data() + "/config";
+	}
+
+	static inline QString db() {
+		return data() + "/db";
+	}
+
+	static inline QString pic() {
+		return data() + "/pic";
+	}
+
+	static inline QString rec() {
+		return data() + "/rec";
+	}
+
+	static inline QString currentTimeString() {
+		return QDateTime::currentDateTime().toString(FILE_TIME_FORMAT);
+	}
+};
+
+struct AutoSwithToBin {
+	AutoSwithToBin() {}
+
+	AutoSwithToBin(const QString& path) {
+		QDir().setCurrent(path);
+	}
+
+	~AutoSwithToBin() {
+		QDir().setCurrent(PathHelper::bin());
+	}
+};
+
+} // end of namespace qt
+} // end of namespace jlib
diff --git a/test/qt_test/qt/QtStylesheet.h b/test/qt_test/qt/QtStylesheet.h
new file mode 100644
index 0000000..53dea33
--- /dev/null
+++ b/test/qt_test/qt/QtStylesheet.h
@@ -0,0 +1,360 @@
+#pragma once
+
+#include <QString>
+#include <QColor>
+
+namespace jlib {
+namespace qt {
+
+namespace def_sizes {
+
+static const int window_width = 646;
+static const int window_height = 424;
+
+static const int title_height = 54;
+
+static const int content_height = window_height - title_height;
+static const int control_height = 24;
+
+static const int big_window_width = 1022;
+static const int big_window_height = 670;
+static const int big_content_height = big_window_height - title_height;
+
+static const int device_view_width = 306;
+static const int device_view_height = 236;
+
+} // namespace def_sizes
+
+
+namespace def_colors {
+
+// 0x202224
+static const auto window_bk = QColor(0x202224);
+// 0x2c2d30
+static const auto control_bk = QColor(0x2c2d30);
+// 0x26272a
+static const auto control_bk2 = QColor(0x26272a);
+// 0x313235
+static const auto control_bk_suspend = QColor(0x313235);
+// 0x424446
+static const auto control_bk_unknown = QColor(0x424446);
+// 0xd7d5d5
+static const auto unknown_trans = QColor(0xd7d5d5);
+// 0xfd8b30
+static const auto control_text_font = QColor(0xfd8b30);
+
+// 0xb0afaf
+static const auto icon_text_color = QColor(0xb0afaf);
+
+// 0xfe3e3e
+static const auto hint_color = QColor(0xfe3e3e);
+// 0xa8a9a9
+static const auto edit_color = QColor(0xa8a9a9);
+
+// 0x626466
+static const auto bg_normal = QColor(0x626466);
+// 0x727476
+static const auto bg_suspend = QColor(0x727476);
+// 0xbbbbbb
+static const auto font_normal = QColor(0xbbbbbb);
+// 0xf1f1f1
+static const auto font_suspend = QColor(0xf1f1f1);
+// 0x838383
+static const auto font_normal2 = QColor(0x838383);
+// 0xaaaaaa
+static const auto font_normal3 = QColor(0xaaaaaa);
+// 0x929292
+static const auto font_normal4 = QColor(0x929292);
+
+// 0x1a1a1a
+static const auto ptz_border = QColor(0x1a1a1a);
+// 0x2d2e31
+static const auto ptz_back = QColor(0x2d2e31);
+
+} // namespace def_colors
+
+
+namespace def_font_families {
+
+static const char* const yahei = "Microsoft YaHei";
+
+} // namespace def_font_families
+
+
+inline QString color_value_to_string(int value) {
+	auto s = QString::number(value, 16);
+	if (s.length() == 1) { s += "0"; }
+	return s;
+}
+
+inline QString color_to_string_16(QColor color) {
+	return color_value_to_string(color.red()) + color_value_to_string(color.green()) + color_value_to_string(color.blue());
+}
+
+// background:[style];
+inline QString build_bg_style(QString style = "transparent") {
+	return QString("background:") + style + QString(";");
+}
+
+// color:#[color];
+inline QString build_color_style(QColor color) {
+	return QString("color:#") + color_to_string_16(color) + QString(";");
+}
+
+// background-color:#[color];
+inline QString build_bgcolor_style(QColor bgcolor) {
+	return QString("background-color:#") + color_to_string_16(bgcolor) + QString(";");
+}
+
+// background-color:rgba([r],[g],[b],[a]%);
+inline QString build_bgcolor_style(int r, int g, int b, int a) {
+	return QString("background-color:rgba(%1,%2,%3,%4%);").arg(r).arg(g).arg(b).arg(a);
+}
+
+// border:[border]px;
+inline QString build_border_style(size_t border) {
+	return QString("border:") + QString::number(border) + QString("px;");
+}
+
+// font:[font_size]pt;font-family:[font_family];
+inline QString bulid_font_style(size_t font_size, QString font_family = def_font_families::yahei) {
+	return QString("font:") + QString::number(font_size) + QString("pt;")
+		+ QString("font-family:") + font_family + QString(";");
+}
+
+// color:#[color];font:[font_size]pt;font-family:[font_family];
+inline QString build_style(QColor color, size_t font_size, QString font_family = def_font_families::yahei) {
+	return build_color_style(color)	+ bulid_font_style(font_size, font_family);
+}
+
+// background-color:#[color];color:#[color];font:[font_size]pt;font-family:[font_family];[border:[border]px;]
+inline QString build_style(QColor bgcolor, QColor color, size_t font_size, 
+						   QString font_family = def_font_families::yahei, 
+						   bool with_border = false, size_t border = 0) {
+	auto style = build_bgcolor_style(bgcolor) + build_style(color, font_size, font_family);
+	if (with_border) { style += build_border_style(border); }
+	return style;
+}
+
+// background-color:rgba([r],[g],[b],[a]%);color:#[color];font:[font_size]pt;font-family:[font_family];
+inline QString build_style(int r, int g, int b, int a, QColor color, size_t font_size,
+						   QString font_family = def_font_families::yahei) {
+	return build_bgcolor_style(r, g, b, a) + build_style(color, font_size, font_family);
+}
+
+
+namespace def_style_sheets {
+
+// color:#ffffff;font:11pt;font-family:Microsoft YaHei;
+inline QString label() {
+	return build_style(Qt::white, 11);
+}
+
+// color:#fe3e3e;font:9pt;font-family:Microsoft YaHei;
+inline QString hint() {
+	return build_style(def_colors::hint_color, 9);
+}
+
+// color:#202224;font:12pt;font-family:Microsoft YaHei;border:0px;
+inline QString edit() {
+	return build_style(def_colors::window_bk, def_colors::edit_color, 12, def_font_families::yahei, true);
+}
+
+// color:#424446;font:11pt;font-family:Microsoft YaHei;border:0px;
+inline QString unknown() {
+	return build_style(def_colors::control_bk_unknown, def_colors::edit_color, 11, def_font_families::yahei, true);
+}
+
+// background:transparent;color:#d7d5d5;font:18pt;font-family:Microsoft YaHei;
+inline QString unkonwn_trans() {
+	return build_bg_style() + build_style(def_colors::unknown_trans, 18);
+}
+
+static const auto vertical_scroll_bar = R"(
+QScrollBar:vertical
+{
+	width:8px;
+	background:rgba(0,0,0,0%);
+	margin:0px,0px,0px,0px;
+	padding-top:0px;
+	padding-bottom:0px;
+}
+
+QScrollBar::handle:vertical
+{
+	width:8px;
+	background:#444547;
+	border-radius:4px;
+	min-height:20;
+}
+
+QScrollBar::handle:vertical:hover
+{
+	width:8px;
+	background:#444547;
+	border-radius:4px;
+	min-height:20;
+}
+
+QScrollBar::add-line:vertical
+{
+	height:9px;
+	width:8px;
+	border-image:url(:/images/a/3.png);
+	subcontrol-position:bottom;
+}
+
+QScrollBar::sub-line:vertical
+{
+	height:9px;
+	width:8px;
+	border-image:url(:/images/a/1.png);
+	subcontrol-position:top;
+}
+
+QScrollBar::add-line:vertical:hover
+{
+	height:9px;
+	width:8px;
+	border-image:url(:/images/a/4.png);
+	subcontrol-position:bottom;
+}
+
+QScrollBar::sub-line:vertical:hover
+{
+	height:9px;
+	width:8px;
+	border-image:url(:/images/2.png);
+	subcontrol-positino:top;
+}
+
+QScrollBar::add-page:vertical,QScrollBar::sub-page:vertical
+{
+	background:rgba(0,0,0,10%);
+	border-radius:4px;
+}
+
+)";
+
+static const auto search_bar_edit = R"(
+border: 0px;
+background: transparent;
+selection-background-color: white;
+color: #a8a9a9;
+font-family: Microsoft Yahei;
+font-size: 14px;
+)";
+
+static const auto progress_bar = R"(
+QProgressBar{
+	background-color:#dedede;border-radius:3px;
+}
+QProgressBar::chunk{
+	background-color:#fd8b30;border-radius:3px;
+}
+)";
+
+static const auto slider = R"(
+QSlider::groove:horizontal
+{
+	border:0px;
+	height:4px;
+	background:rgb(0,0,0);
+}
+QSlider::sub-page:horizontal
+{
+	background:#fd8b30;
+}
+QSlider::add-page:horizontal
+{
+	background:#141414;
+}
+QSlider::handle:horizontal
+{
+	background:white;
+	width:10px;
+	border-radius:5px;
+	margin:-3px 0px -3px 0px;
+}
+)";
+
+static const auto menu = R"(
+QMenu::item 
+{
+	font-family: Microsoft Yahei; 
+	font-size: 12pt; 
+	color: #808080; 
+	border: 1px solid gray; 
+	background-color: rgb(234,234,234);
+}
+QMenu::item:hover 
+{
+	background-color: rgb(0, 0, 255);
+}
+)";
+
+static const auto group_box = R"(
+QGroupBox {
+    border: 1px solid gray;
+    border-radius: 9px;
+    margin-top: 0.5em;
+	font: 24pt;
+	font-family: Microsoft Yahei;
+}
+QGroupBox::title {
+    subcontrol-origin: margin;
+    left: 20px;
+    padding: 0 3px 0 3px;
+	color: white;
+}
+)";
+
+static const auto listWidgetStyleSheet = R"(
+QListWidget 
+{ 
+	font:12pt; 
+	font-family:Microsoft Yahei; 
+	background-color: #2c2d30; 
+	border: 1px solid black; 
+} 
+
+QListWidget::item 
+{ 
+	color:#fd8b30; 
+	border: 1px solid silver;
+} 
+
+QListWidget::item::selected 
+{ 
+	color:#fd8b30; 
+	border: 3px solid yellow;
+}
+)";
+
+
+static const auto check_box = R"(
+QCheckBox
+{
+	font-size: 16px;
+	color: white;
+}
+QCheckBox::indicator
+{
+	width: 48px;
+	height: 48px;
+}
+QCheckBox::indicator:checked
+{
+	image: url(:/Skin/checkbox/checkbox_checked.png);
+}
+QCheckBox::indicator:unchecked
+{
+	image: url(:/Skin/checkbox/checkbox_unchecked.png);
+}
+)";
+
+} // end of namespace def_style_sheets
+
+
+} // end of namespace qt
+} // end of namespace jlib
diff --git a/test/qt_test/qt/QtUtils.h b/test/qt_test/qt/QtUtils.h
new file mode 100644
index 0000000..308df85
--- /dev/null
+++ b/test/qt_test/qt/QtUtils.h
@@ -0,0 +1,127 @@
+#pragma once
+
+#include <cassert>
+#include <QString>
+#include <QColor>
+#include <QPixmap>
+#include <QApplication>
+#include <QDesktopwidget>
+#include <QIcon>
+#include <QTimer>
+#include <QDir>
+#include <QProcess>
+#include "QtDebug.h"
+#include "QtPathHelper.h"
+
+
+namespace jlib {
+namespace qt {
+
+/**
+* @brief 不阻塞UI响应的情况下,等待一段时间
+* @param ms 等待的毫秒数
+*/
+static inline void non_blocking_wait_in_ui_thread(int ms) {
+	QEventLoop q;
+	QTimer t;
+	t.setSingleShot(true);
+	QObject::connect(&t, &QTimer::timeout, &q, &QEventLoop::quit);
+	t.start(ms);
+	q.exec();
+}
+
+/**
+* @brief 在文件夹中显示
+* @param pathIn 若为文件路径则在文件夹中显示,若为文件夹路径则打开改文件夹
+*/
+static inline void showInGraphicalShell(const QString &pathIn) {
+	QString param;
+	if (!QFileInfo(pathIn).isDir())
+		param = QLatin1String("/select,");
+	param += QDir::toNativeSeparators(pathIn);
+	QString command = "explorer.exe " + param;
+	QProcess::startDetached(command);
+}
+
+static inline bool warn_if_load_pixmap_failed(QPixmap& pixmap, QString icon_path, QString file_line)
+{
+	if (!QDir().isAbsolutePath(icon_path)) {
+		icon_path = PathHelper::program() + "/" + icon_path;
+	}
+	
+	if (!pixmap.load(icon_path) && !pixmap.load(icon_path, "png")) {
+		qCritical() << file_line << "load pixmap failed: " << icon_path;
+		assert(0);
+		return false;
+	}
+	return true;
+}
+
+#define LOAD_PIXMAP_EX(icon_path) jlib::qt::warn_if_load_pixmap_failed(pixmap, icon_path, QDEBUG_FILE_LINE_VER)
+
+static QIcon icon_from_path(QString path, QSize icon_sz) {
+	QPixmap pixmap;
+	LOAD_PIXMAP_EX(path);
+	return QIcon(pixmap.scaled(icon_sz, Qt::KeepAspectRatio, Qt::SmoothTransformation));
+}
+
+static inline void fill_bg_with_color(QWidget * widget, QColor color)
+{
+	if (!widget) { return; }
+
+	widget->setAutoFillBackground(true);
+	QPalette palette;
+	palette.setColor(QPalette::Background, color);
+	widget->setPalette(palette);
+}
+
+static inline void set_pos(QWidget * widget, QRect pos)
+{
+	if (!widget) { return; }
+	widget->setFixedSize(pos.width(), pos.height());
+	widget->move(pos.left(), pos.top());
+}
+
+static inline void set_image_bg(QWidget* widget, QPixmap pixmap)
+{
+	if (!widget || pixmap.isNull())return;
+	QPalette palette;
+	palette.setBrush(QPalette::Window, QBrush(pixmap));
+	widget->setPalette(palette);
+}
+
+static inline void set_image_bg(QWidget* widget, QString icon_path)
+{
+	QPixmap pixmap;
+	if (!LOAD_PIXMAP_EX(icon_path)) { return; }
+	set_image_bg(widget, pixmap);
+}
+
+static inline void center_to_parent(QWidget* widget, QWidget* parent)
+{
+	if (!widget || !parent) { return; }
+	auto center = parent->rect().center();
+	widget->move(center.x() - widget->width() / 2, center.y() - widget->height() / 2);
+}
+
+static inline void center_to_desktop(QWidget* widget)
+{
+	if (!widget) { return; }
+	auto center = QApplication::desktop()->availableGeometry(widget).center();
+	widget->move(center.x() - widget->width() / 2, center.y() - widget->height() / 2);
+}
+
+static inline void center_to_desktop(QWidget* widget, int new_width, int new_height)
+{
+	if (!widget) { return; }
+	auto center = QApplication::desktop()->availableGeometry(widget).center();
+	widget->setFixedSize(new_width, new_height);
+	widget->move(center.x() - new_width / 2, center.y() - new_height / 2);
+	widget->adjustSize();
+}
+
+
+
+
+}
+}
diff --git a/test/qt_test/qt/View/BgColorBtn.h b/test/qt_test/qt/View/BgColorBtn.h
new file mode 100644
index 0000000..6a43dc1
--- /dev/null
+++ b/test/qt_test/qt/View/BgColorBtn.h
@@ -0,0 +1,75 @@
+#pragma once
+
+#include <QPushButton>
+#include "../QtStylesheet.h"
+
+namespace jlib
+{
+namespace qt
+{
+
+class BgColorBtn : public QPushButton
+{
+	Q_OBJECT
+
+public:
+	BgColorBtn(QWidget *parent = nullptr)
+		: QPushButton(parent)
+	{
+		connect(this, &QPushButton::clicked, this, &BgColorBtn::slot_clicked);
+	}
+
+	virtual ~BgColorBtn() {}
+
+	void set_btn_attr(QColor bg_normal, QColor bg_suspend, QColor font_color, unsigned int font_sz) {
+		bg_normal_ = bg_normal;
+		bg_suspend_ = bg_suspend;
+		font_color_ = font_color;
+		font_sz_ = font_sz;
+		set_normal_attr();
+	}
+
+	void set_tag(int tag) { tag_ = tag; }
+	int tag() const { return tag_; }
+
+signals:
+	void sig_clicked(int tag);
+
+private slots:
+	void slot_clicked();
+
+protected:
+	virtual void enterEvent(QEvent* e) override {
+		if (!isEnabled() || (parent() && !parentWidget()->isEnabled()))return;
+		set_mouse_enter_attr(); setCursor(QCursor(Qt::PointingHandCursor));
+	}
+
+	virtual void leaveEvent(QEvent* e) override {
+		if (!isEnabled() || (parent() && !parentWidget()->isEnabled()))return;
+		set_normal_attr(); setCursor(QCursor(Qt::ArrowCursor));
+	}
+
+private:
+	void set_normal_attr() { set_attr(bg_normal_, font_color_, font_sz_); }
+	void set_mouse_enter_attr() { set_attr(bg_suspend_, font_color_, font_sz_); }
+	void set_attr(QColor bg_color, QColor font_color, unsigned int font_sz) {
+		setStyleSheet(build_style(bg_color, font_color, font_sz));
+	}
+
+private:
+	QColor bg_normal_ = {};
+	QColor bg_suspend_ = {};
+	QColor font_color_ = {};
+	unsigned int font_sz_ = {};
+	int tag_ = -1;
+};
+
+inline void BgColorBtn::slot_clicked()
+{
+	if (tag_ != -1) {
+		emit sig_clicked(tag_);
+	}
+}
+	
+} // namespace qt
+} // namespace jlib
diff --git a/test/qt_test/qt/View/HttpDlg.h b/test/qt_test/qt/View/HttpDlg.h
new file mode 100644
index 0000000..20d8647
--- /dev/null
+++ b/test/qt_test/qt/View/HttpDlg.h
@@ -0,0 +1,212 @@
+#pragma once
+
+#include <QDialog>
+#include <QLabel>
+#include <QElapsedTimer>
+#include <QUrl>
+#include <QNetworkRequest>
+#include <QByteArray>
+#include <qmovie.h>
+#include <qnetworkaccessmanager.h>
+#include <qnetworkreply.h>
+#include <system_error>
+#include "../QtPathHelper.h"
+#include "../QtUtils.h"
+#include "../QtStylesheet.h"
+#include "HttpDlgErrorCode.h"
+#include <jlib/3rdparty/json/jsoncpp/json.h>
+
+namespace jlib
+{
+namespace qt
+{
+
+class HttpDlg : public QDialog
+{
+	Q_OBJECT
+
+public:
+	enum HttpDlgViewSize {
+		sz_big,
+		sz_small,
+	};
+
+	HttpDlg(QWidget *parent = nullptr, HttpDlgViewSize sz = sz_big, int timeOut = 10)
+		: QDialog(parent)
+		, sz_(sz)
+		, time_out_sec_(timeOut)
+	{
+		setWindowModality(Qt::WindowModal);
+		setWindowFlags(Qt::FramelessWindowHint);
+		if (!parent) { setAttribute(Qt::WA_TranslucentBackground); }
+
+		if (sz == sz_small) { setFixedSize(200, 200);
+		} else { setFixedSize(630, 637); }
+
+		label_ = new QLabel(this); label_->resize(width(), height()); label_->move(0, 0);
+
+		elapse_ = new QLabel(this); elapse_->resize(180, 80);
+		elapse_->move((width() - elapse_->width()) / 2, (height() - elapse_->height()) / 2);
+		elapse_->setStyleSheet(build_style(Qt::darkYellow, 64));
+		elapse_->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+		//elapse_->hide();
+
+		parent ? center_to_parent(this, parent) : center_to_desktop(this);
+		mgr = new QNetworkAccessManager(this);
+	}
+
+	~HttpDlg() {}
+
+	void get(const QUrl& url) {
+		if (connection_) { disconnect(connection_); }
+		connection_ = connect(mgr, &QNetworkAccessManager::finished, this, &HttpDlg::onFinished);
+		reply_ = mgr->get(QNetworkRequest(url));
+		run();
+	}
+
+	void post(const QUrl& url) {
+		if (connection_) { disconnect(connection_); }
+		connection_ = connect(mgr, &QNetworkAccessManager::finished, this, &HttpDlg::onFinished);
+		QNetworkRequest request(url);
+		request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
+		reply_ = mgr->post(request, QByteArray());
+		run();
+	}
+
+	void post(const QNetworkRequest& request, const QByteArray& data) {
+		if (connection_) { disconnect(connection_); }
+		connection_ = connect(mgr, &QNetworkAccessManager::finished, this, &HttpDlg::onFinished);
+		reply_ = mgr->post(request, data);
+		run();
+	}
+
+	std::error_code get_result() const { return result_; }
+	Json::Value getRoot() const { return root_; }
+
+	bool getValue(const QString& name, Json::Value& value) {
+		if (root_.isMember(name.toStdString())) {
+			value = root_[name.toStdString()];
+			return true;
+		} return false;
+	}
+
+	bool getValue(const QString& name, QString& value) {
+		Json::Value val;
+		if (getValue(name, val)) {
+			value = QString::fromUtf8(val.asCString());
+			return true;
+		} return false;
+	}
+
+	bool getValue(const QString& name, int& value) {
+		Json::Value val;
+		if (getValue(name, val)) {
+			value = val.asInt();
+			return true;
+		} return false;
+	}
+
+	int getHttpStatusCode() const { return httpStatusCode_; }
+	QString getHttpReason() const { return httpReason_; }
+
+#define break_if_parse_int_value_failed(json, name, default_value) \
+int name = default_value; \
+if (!JsoncppHelper::safelyGetIntValue(json, #name, name)) { \
+	ec = HttpDlgErrorCode::ParseJsonError; \
+	break; \
+}
+
+#define break_if_parse_string_value_failed(json, name, default_value) \
+QString name = default_value; \
+if (!JsoncppHelper::safelyGetStringValue(json, #name, name)) { \
+	ec = HttpDlgErrorCode::ParseJsonError; \
+	break; \
+}
+
+protected:
+	void run() {
+		auto path = PathHelper::program();
+		path += sz_ == sz_small ? "/Skin/gif/ajax-loader-small.gif" : "/Skin/gif/preloader.gif";
+		auto movie = new QMovie(path);
+		label_->setMovie(movie);
+		movie->start();
+		timer_.start();
+
+		auto p = parentWidget();
+		if (p) { p->setEnabled(false); }
+
+		startTimer(1000);
+		QDialog::exec();
+		if (p) { p->setEnabled(true); }
+
+		movie->deleteLater();
+	}
+
+	virtual void timerEvent(QTimerEvent * e) override {
+		MYQDEBUG << time_out_sec_;
+		if (--time_out_sec_ > 0) { elapse_->setText(QString::number(time_out_sec_)); } 
+		else {
+			MYQCRITICAL << "timeout";
+			disconnect(connection_); result_ = HttpDlgErrorCode::NetworkError;
+			QDialog::reject();
+		}
+	}
+
+private slots:
+	void onFinished(QNetworkReply* reply) {
+		do {
+			if (!reply) {
+				MYQCRITICAL << "no reply"; result_ = HttpDlgErrorCode::NetworkError;
+				break;
+			}
+
+			if (QNetworkReply::NoError != reply->error()) {
+				httpReason_ = reply->errorString(); MYQCRITICAL << httpReason_;
+				result_ = HttpDlgErrorCode::NetworkError;
+				break;
+			}
+
+			QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
+			if (!statusCode.isValid()) { MYQDEBUG << "statusCode is not valid"; break; }
+
+			httpStatusCode_ = statusCode.toInt();
+			if (httpStatusCode_ != 200) {
+				result_ = HttpDlgErrorCode::NetworkError;
+				httpReason_ = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
+				MYQCRITICAL << httpStatusCode_ << httpReason_;
+				break;
+			}
+
+			auto res = reply->readAll();
+			Json::Reader reader; root_.clear();
+			if (!reader.parse(res.constData(), root_)) {
+				//result_ = HttpDlgErrorCode::ParseJsonError;
+				//break;
+			}
+
+			MYQDEBUG << reply->url() << "reply:\n" << root_.toStyledString().data();
+		} while (false);
+
+		QDialog::accept();
+		reply->deleteLater();
+	}
+
+private:
+	std::error_code result_ = {};
+	int httpStatusCode_ = 0;
+	QString httpReason_ = {};
+	Json::Value root_ = {};
+	int time_out_sec_ = 10;
+	QNetworkAccessManager* mgr = {};
+	QNetworkReply* reply_ = {};
+	QMetaObject::Connection connection_ = {};
+
+	QLabel* label_ = {};
+	QLabel* elapse_ = {};
+	HttpDlgViewSize sz_ = sz_big;
+	QElapsedTimer timer_ = {};
+
+};
+
+}
+}
diff --git a/test/qt_test/qt/View/HttpDlgErrorCode.h b/test/qt_test/qt/View/HttpDlgErrorCode.h
new file mode 100644
index 0000000..61c240b
--- /dev/null
+++ b/test/qt_test/qt/View/HttpDlgErrorCode.h
@@ -0,0 +1,57 @@
+#pragma once
+#include <QString>
+#include <QObject>
+#include "../ErrorCode.h"
+
+namespace jlib
+{
+namespace qt
+{
+
+enum class HttpDlgErrorCode {
+	NetworkError = 1,
+	ParseJsonError,
+
+};
+
+}
+}
+
+namespace std {
+ENABLE_ENUM_AS_ERROR_CODE(jlib::qt::HttpDlgErrorCode);
+}
+
+
+namespace
+{
+
+class HttpDlgErrorCategory : public std::error_category
+{
+public:
+	const char* name() const noexcept override {
+		return "HttpClient";
+	}
+
+	std::string message(int ev) const override {
+		switch (static_cast<jlib::qt::HttpDlgErrorCode>(ev)) {
+			case jlib::qt::HttpDlgErrorCode::NetworkError:
+				return QObject::tr("Network Error").toLocal8Bit().toStdString();
+				break;
+			case jlib::qt::HttpDlgErrorCode::ParseJsonError:
+				return QObject::tr("Cannot Parse Json").toLocal8Bit().toStdString();
+				break;
+			default:
+				return QObject::tr("Unkown Error").toLocal8Bit().toStdString();
+				break;
+		}
+	}
+};
+
+static const HttpDlgErrorCategory theHttpDlgErrorCategory = {};
+
+}
+
+inline std::error_code std::make_error_code(jlib::qt::HttpDlgErrorCode ec)
+{
+	return { static_cast<int>(ec), theHttpDlgErrorCategory };
+}
\ No newline at end of file
diff --git a/test/qt_test/qt/View/IconBtn.h b/test/qt_test/qt/View/IconBtn.h
new file mode 100644
index 0000000..da27f8f
--- /dev/null
+++ b/test/qt_test/qt/View/IconBtn.h
@@ -0,0 +1,150 @@
+#pragma once
+
+#include <QLabel>
+#include <QMouseEvent>
+#include <QPixmap>
+#include <QBitmap>
+#include "../QtUtils.h"
+
+namespace jlib
+{
+namespace qt
+{
+
+class IconBtn : public QLabel
+{
+	Q_OBJECT
+
+public:
+	enum IconStatus : uint32_t {
+		status_normal = 0x00000001,
+		status_hover = 0x00000002,
+		status_press = 0x00000004,
+		status_disable = 0x00000008,
+		status_ing = 0x00000010,
+
+		// 不规则按钮
+		type_mask = 0x00000020,
+		// 不重绘已绘制区域(原demo建议尽量不用)
+		type_opaque_paint = 0x00000040,
+		// 长按功能
+		type_long_press = 0x00000080,
+
+		status_default = status_normal | status_hover | status_press,
+	};
+
+	IconBtn(QWidget *parent, QString icon_path, uint32_t state_set = IconStatus::status_default)
+		: QLabel(parent)
+		, icon_path_(icon_path)
+		, state_set_(state_set)
+	{
+		setAttribute(Qt::WA_TranslucentBackground, true);
+		long_press_timer_ = new QTimer(this);
+		connect(long_press_timer_, &QTimer::timeout, this, &IconBtn::slot_long_press_timeout);
+		state_set_ |= IconStatus::status_normal;
+		set_icon_path(icon_path_);
+	}
+
+	void set_pos(const QPoint& pos) { move(pos); }
+	void set_pos(int x, int y) { set_pos(QPoint(x, y)); }
+	void set_icon_path(const QString& icon_path) { icon_path_ = icon_path; refresh_icon_status(); }
+	void set_enabled(bool enable) { is_enable_ = enable; refresh_icon_status(); }
+	void set_ing_status(bool is_ing) { is_ing_status_ = is_ing; refresh_icon_status(); }
+	bool is_ing_status() const { return is_ing_status_; }
+
+protected:
+	virtual void enterEvent(QEvent*) override {
+		if (!is_enable_) { return; }
+		setCursor(QCursor(Qt::PointingHandCursor));
+		is_mouse_hover_ = true;
+		refresh_icon_status();
+		emit sig_mouse_enter();
+	}
+
+	virtual void leaveEvent(QEvent*) override {
+		setCursor(QCursor(Qt::ArrowCursor));
+		is_mouse_hover_ = false;
+		is_mouse_press_ = false;
+		refresh_icon_status();
+		emit sig_mouse_leave();
+	}
+
+	virtual void mousePressEvent(QMouseEvent*) override {
+		if (!is_enable_) { return; }
+		is_mouse_press_ = true;
+		refresh_icon_status();
+		if (state_set_ & type_long_press) {
+			if (long_press_timer_->isActive()) {
+				long_press_timer_->stop();
+			}
+			long_press_timer_->setSingleShot(true);
+			long_press_timer_->start(450);
+		}
+	}
+
+	virtual void mouseReleaseEvent(QMouseEvent* e) override {
+		if (!is_enable_) { return; }
+		if (long_press_timer_->isActive()) { long_press_timer_->stop(); }
+		bool is_long_press = is_long_press_;
+		is_long_press_ = is_mouse_press_ = false;
+		refresh_icon_status();
+		if (Qt::LeftButton == e->button() && rect().contains(e->pos())) {
+			is_long_press ? emit long_press_trigger(false) : emit clicked();
+		}
+	}
+
+signals:
+	void clicked();
+	void long_press_trigger(bool is_press);
+	void sig_mouse_enter();
+	void sig_mouse_leave();
+
+private slots:
+	void slot_long_press_timeout();
+
+private:
+	unsigned long state_set_ = 0;
+	QString icon_path_ = {};
+	bool is_enable_ = true;
+	bool is_ing_status_ = false;
+	bool is_mouse_hover_ = false;
+	bool is_mouse_press_ = false;
+	QTimer* long_press_timer_ = {};
+	bool is_long_press_ = false;
+
+	void refresh_icon_status() {
+		QString icon_path;
+		if (!is_enable_) {
+			if (!(state_set_ & status_disable)) { return; }
+			icon_path = icon_path_ + "_d.png";
+		} else if (is_mouse_press_) {
+			if (!(state_set_ & status_press)) { return; }
+			icon_path = icon_path_ + "_h.png";
+		} else if (is_ing_status_) {
+			if (!(state_set_ & status_ing)) { return; }
+			icon_path = icon_path_ + "_ing.png";
+		} else if (is_mouse_hover_) {
+			if (!(state_set_ & status_hover)) { return; }
+			icon_path = icon_path_ + "_p.png";
+		} else {
+			if (!(state_set_&status_normal)) { return; }
+			icon_path = icon_path_ + "_n.png";
+		}
+
+		QPixmap pixmap;
+		if (!LOAD_PIXMAP_EX(icon_path)) { return; }
+		setFixedSize(pixmap.size()); setPixmap(pixmap);
+		if (state_set_ & type_mask) { setMask(pixmap.mask()); }
+		if (state_set_ & type_opaque_paint) { setAttribute(Qt::WA_OpaquePaintEvent, true); }
+	}
+
+};
+
+inline void IconBtn::slot_long_press_timeout()
+{
+	is_long_press_ = true;
+	emit long_press_trigger(true);
+}
+
+}
+}
diff --git a/test/qt_test/qt/View/LoadingView.h b/test/qt_test/qt/View/LoadingView.h
new file mode 100644
index 0000000..f53d3d5
--- /dev/null
+++ b/test/qt_test/qt/View/LoadingView.h
@@ -0,0 +1,194 @@
+#pragma once
+
+#include <QDialog>
+#include <qlabel.h>
+#include "../Ctrl/ThreadCtrl.h"
+#include "../Model/ThreadModel.h"
+#include <vector>
+#include <qelapsedtimer.h>
+#include <qmovie.h>
+#include "../QtUtils.h"
+#include "../QtStylesheet.h"
+#include "../QtPathHelper.h"
+
+namespace jlib
+{
+namespace qt
+{
+
+class LoadingView : public QDialog
+{
+	Q_OBJECT
+
+public:
+	enum LoadingViewSize {
+		sz_big,
+		sz_small,
+	};
+
+	LoadingView(QWidget *parent = nullptr, std::vector<ThreadCtrl*> threads = {}, LoadingViewSize sz = sz_big)
+		: QDialog(parent)
+		, threads_(threads)
+		, sz_(sz)
+	{
+		setWindowModality(Qt::WindowModal);
+		setWindowFlags(Qt::FramelessWindowHint);
+		if (!parent) { setAttribute(Qt::WA_TranslucentBackground); }
+
+		if (sz == sz_small) { setFixedSize(200, 200);
+		} else { setFixedSize(630, 637); }
+
+		label_ = new QLabel(this); label_->resize(width(), height()); label_->move(0, 0);
+
+		progress1_ = new QLabel(this); progress1_->resize(180, 80);
+		progress2_ = new QLabel(this); progress2_->resize(180, 50);
+		elapse_ = new QLabel(this); elapse_->resize(180, 50);
+
+		progress1_->move((width() - progress1_->width()) / 2, (height() - progress1_->height() - progress2_->height() - elapse_->height()) / 2);
+		progress1_->setStyleSheet(build_style(Qt::green, 64));
+		progress1_->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+		progress1_->hide();
+
+		progress2_->move(progress1_->x(), progress1_->y() + progress1_->height());
+		progress2_->setStyleSheet(build_style(Qt::blue, 32));
+		progress2_->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+		progress2_->hide();
+
+		elapse_->move(progress1_->x(), progress2_->y() + progress2_->height());
+		elapse_->setStyleSheet(build_style(Qt::darkYellow, 48));
+		elapse_->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
+		elapse_->hide();
+
+		parent ? center_to_parent(this, parent) : center_to_desktop(this);
+
+		int tag = 0;
+		for (auto& thread_ : threads_) {
+			thread_->set_tag(tag++);
+			tp_.push_back(ThreadProgress(0, 1));
+			connect(thread_, SIGNAL(sig_ready(int, std::error_code)), this, SLOT(slot_ready(int, std::error_code)));
+			connect(thread_, SIGNAL(sig_progress(int, HBVideoPlatform::common::ThreadProgress)), this, SLOT(slot_progress(int, HBVideoPlatform::common::ThreadProgress)));
+		}
+	}
+
+	virtual ~LoadingView() {
+		for (auto thread_ : threads_) {
+			thread_->deleteLater();
+		}
+	}
+
+	void run() {
+		auto path = PathHelper::program();;
+		path += sz_ == sz_small ? "/Skin/gif/ajax-loader-small.gif" : "/Skin/gif/preloader.gif";
+		auto movie = new QMovie(path);
+		label_->setMovie(movie);
+		movie->start();
+
+		timer_.start();
+
+		for (auto thread_ : threads_) {
+			thread_->start();
+		}
+
+		auto p = parentWidget();
+		if (p) {
+			p->setEnabled(false);
+		}
+
+		if (!show_progress_) {
+			show_progress_ = true;
+			startTimer(1000);
+		}
+
+		QDialog::exec();
+		if (p) {
+			p->setEnabled(true);
+		}
+	}
+
+	std::error_code get_result() const { return result_; }
+
+private slots:
+	void slot_ready(int tag, std::error_code ec);
+	void slot_progress(int tag, jlib::qt::ThreadProgress progress);
+
+protected:
+	virtual void timerEvent(QTimerEvent* e) override {
+		if (show_progress_) {
+			int secs = timer_.elapsed() / 1000;
+			int mins = secs / 60;
+			secs %= 60;
+			elapse_->setText(QString().sprintf("%02d:%02d", mins, secs));
+			elapse_->show();
+		}
+	}
+
+private:
+	std::error_code result_ = {};
+	std::vector<ThreadCtrl*> threads_ = {};
+
+	QLabel* label_ = {};
+	QLabel* progress1_ = {};
+	QLabel* progress2_ = {};
+	QLabel* elapse_ = {};
+	std::vector<ThreadProgress> tp_ = {};
+	bool show_progress_ = false;
+	LoadingViewSize sz_ = sz_big;
+
+	QElapsedTimer timer_ = {};
+};
+
+inline void LoadingView::slot_progress(int tag, jlib::qt::ThreadProgress progress)
+{
+	tp_[tag].total = progress.total;
+	tp_[tag].pos = progress.pos;
+	int pos = 0; int total = 0;
+	for (auto tp : tp_) {
+		pos += tp.pos;
+		total += tp.total;
+	}
+
+	int percent = pos * 100 / total;
+	MYQDEBUG << "tag" << tag << "progress.pos" << progress.pos << "progress.total" << progress.total << "pos" << pos << "total" << total << "percent" << percent;
+
+	progress1_->setText(QString("%1%").arg(percent));
+	progress1_->show();
+
+	progress2_->setText(QString("%1/%2").arg(pos).arg(total));
+	progress2_->show();
+
+	int secs = timer_.elapsed() / 1000;
+	int mins = secs / 60;
+	secs %= 60;
+	elapse_->setText(QString().sprintf("%02d:%02d", mins, secs));
+	elapse_->show();
+
+
+}
+
+inline void LoadingView::slot_ready(int tag, std::error_code result)
+{
+	MYQDEBUG << "tag" << tag << "ready, code=" << result.value() << "msg=" << QString::fromLocal8Bit(result.message().data());
+	result_ = result;
+
+	if (show_progress_) {
+		progress1_->setText("100%");
+		progress1_->show();
+	}
+
+	for (auto iter = threads_.begin(); iter != threads_.end(); iter++) {
+		auto thread = *iter;
+		if (thread->get_tag() == tag) {
+			threads_.erase(iter);
+			break;
+		}
+	}
+
+	if (!threads_.empty()) { return; }
+
+	QDialog::accept();
+}
+
+
+
+}
+}
diff --git a/test/qt_test/qt/View/PageTitle.h b/test/qt_test/qt/View/PageTitle.h
new file mode 100644
index 0000000..aba8fa7
--- /dev/null
+++ b/test/qt_test/qt/View/PageTitle.h
@@ -0,0 +1,163 @@
+#pragma once
+
+#include <QWidget>
+#include <QPushButton>
+#include <QToolButton>
+#include <QLayout>
+#include <QStyle>
+#include <QLabel>
+#include <QMouseEvent>
+#include <QElapsedTimer>
+#include <QLayout>
+#include <QPixmap>
+#include <QApplication>
+#include "IconBtn.h"
+#include "../QtStylesheet.h"
+
+namespace jlib
+{
+namespace qt
+{
+
+class PageTitle : public QWidget
+{
+	Q_OBJECT
+
+public:
+	PageTitle(QWidget *parent, QString logo_path)
+		: QWidget(parent)
+	{
+		setAutoFillBackground(true);
+
+		QPalette pal = palette();
+		pal.setColor(QPalette::Window, Qt::black);
+		setPalette(pal);
+
+		minimize_ = new IconBtn(this, "Skin/system/min");
+		maximize_ = new IconBtn(this, "Skin/system/max");
+		close_ = new IconBtn(this, "Skin/system/close");
+
+		connect(minimize_, SIGNAL(clicked()), this, SLOT(slot_minimize()));
+		connect(maximize_, SIGNAL(clicked()), this, SLOT(slot_maximize_or_restore()));
+		connect(close_, SIGNAL(clicked()), this, SLOT(slot_close()));
+
+		logo_ = new QLabel(this);
+		QPixmap pixmap;
+		pixmap.load(logo_path);
+		logo_->setFixedSize(32, 32);
+		logo_->setPixmap(pixmap.scaled(32, 32, Qt::KeepAspectRatio));
+
+		title_ = new QLabel(this);
+		//title_->setStyleSheet(def_style_sheets::title);
+		title_->setStyleSheet(build_style(def_colors::font_normal3, 18));
+
+		layout_ = new QHBoxLayout(this);
+		layout_->addWidget(logo_);
+		layout_->addSpacing(5);
+		layout_->addWidget(title_);
+		layout_->addStretch();
+		layout_->addWidget(minimize_);
+		layout_->addWidget(maximize_);
+		layout_->addWidget(close_);
+		layout_->setSpacing(0);
+
+		setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+		setMinimumHeight(7);
+
+		lastTimeClick.start();
+	}
+
+public:
+	void set_title(QString title) {
+		title_->setText(title);
+	}
+	void set_maximize_btn_visible(bool visible) {
+		visible ? maximize_->show() : maximize_->hide();
+	}
+	void set_maximized(bool isMax = true) {
+		is_maximized_ = isMax;
+		if (isMax) {
+			maximize_->set_icon_path("Skin/system/restore");
+			parentWidget()->showMaximized();
+		} else {
+			maximize_->set_icon_path("Skin/system/max");
+			parentWidget()->showNormal();
+		}
+	}
+
+protected:
+	virtual void mousePressEvent(QMouseEvent* e) override {
+		if (!rect().contains(e->pos()))return;
+		is_mouse_pressed_ = true;
+		mouse_pressed_pos_ = mapToParent(e->pos());
+	}
+
+	virtual void mouseMoveEvent(QMouseEvent* e) override {
+		if (!is_mouse_pressed_)return;
+		if (is_maximized_) {
+			maximize_->set_icon_path("Skin/system/max");
+			parentWidget()->showNormal();
+			is_maximized_ = false;
+		}
+		parentWidget()->move(e->globalPos() - mouse_pressed_pos_);
+	}
+
+	virtual void mouseReleaseEvent(QMouseEvent* e) override {
+		is_mouse_pressed_ = false;
+
+		if (lastTimeClick.elapsed() < QApplication::doubleClickInterval()) {
+			slot_maximize_or_restore();
+		}
+
+		lastTimeClick.start();
+	}
+
+signals:
+	void sig_close();
+	void sig_maximized(bool isMax);
+
+private slots:
+	void slot_minimize();
+	void slot_maximize_or_restore();
+	void slot_close();
+
+private:
+	IconBtn* minimize_ = {};
+	IconBtn* maximize_ = {};
+	IconBtn* close_ = {};
+	QLabel* logo_ = {};
+	QLabel* title_ = {};
+	QHBoxLayout* layout_ = {};
+	bool is_maximized_ = false;
+	bool is_mouse_pressed_ = false;
+	QPoint mouse_pressed_pos_ = {};
+	QElapsedTimer lastTimeClick = {};
+};
+
+inline void PageTitle::slot_minimize()
+{
+	parentWidget()->showMinimized();
+}
+
+inline void PageTitle::slot_maximize_or_restore()
+{
+	if (is_maximized_) {
+		maximize_->set_icon_path("Skin/system/max");
+		parentWidget()->showNormal();
+		is_maximized_ = false;
+	} else {
+		maximize_->set_icon_path("Skin/system/restore");
+		parentWidget()->showMaximized();
+		is_maximized_ = true;
+	}
+
+	emit sig_maximized(is_maximized_);
+}
+
+inline void PageTitle::slot_close()
+{
+	emit sig_close();
+}
+
+}
+}
diff --git a/test/qt_test/qt/View/RndButton.h b/test/qt_test/qt/View/RndButton.h
new file mode 100644
index 0000000..f46dff0
--- /dev/null
+++ b/test/qt_test/qt/View/RndButton.h
@@ -0,0 +1,111 @@
+#pragma once
+
+#include <QtWidgets>
+#include "../QtStylesheet.h"
+
+namespace jlib
+{
+namespace qt
+{
+
+class RndButton : public QWidget
+{
+	Q_OBJECT
+
+public:
+	RndButton(QWidget *parent)
+		: QWidget(parent)
+	{
+		txt_ = new QLabel(this);
+		txt_->setAlignment(Qt::AlignCenter);
+		txt_->hide();
+	}
+
+	~RndButton() {}
+
+	void set_attr(QString txt, QSize btn_sz = { 60, 30 }, int font_size = 14) {
+		font_sz_ = font_size;
+		txt_->setStyleSheet(build_style(Qt::white, font_size));
+		txt_->setText(txt);
+		setFixedSize(btn_sz);
+
+		/*QPixmap pixmap;
+		LOAD_PIXMAP_EX(QString::fromLocal8Bit("Skin/Ó¦Óÿò1.png"));
+		QSize pixSize = pixmap.size();
+		pixSize.scale(sz, Qt::KeepAspectRatio);
+		pixmap_ = pixmap.scaled(pixSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);*/
+
+		txt_->resize(size());
+		txt_->move(0, 0);
+		txt_->show();
+
+		bk_color_ = def_colors::control_bk;
+
+		update();
+	}
+
+	void set_highlight(bool on = true) {
+		is_highlighted_ = on;
+		bk_color_ = is_highlighted_ ? Qt::lightGray : def_colors::control_bk;
+		update();
+	}
+
+protected:
+	virtual void paintEvent(QPaintEvent* e) override {
+		QPainter painter(this);
+		painter.setRenderHint(QPainter::Antialiasing, true);
+		QPainterPath path;
+		//int radius = std::min(rect().width() / 20, rect().height() / 20);
+		path.addRoundedRect(QRectF(0, 0, width(), height()), 10, 10);
+		QPen pen(Qt::black, 1);
+		painter.setPen(pen);
+		painter.fillPath(path, bk_color_);
+		painter.drawPath(path);
+	}
+	virtual void enterEvent(QEvent* e) override {
+		setCursor(QCursor(Qt::PointingHandCursor));
+		bk_color_ = Qt::darkGray;
+		update();
+	}
+
+	virtual void leaveEvent(QEvent* e) override {
+		setCursor(QCursor(Qt::ArrowCursor));
+
+		bk_color_ = is_highlighted_ ? Qt::lightGray : def_colors::control_bk;
+		update();
+
+		is_pressed_ = false;
+	}
+
+	virtual void mousePressEvent(QMouseEvent* e) override {
+		bk_color_ = def_colors::control_bk;
+		update();
+
+		is_pressed_ = true;
+	}
+
+	virtual void mouseReleaseEvent(QMouseEvent* e) override {
+		bk_color_ = Qt::darkGray;
+		update();
+
+		if (is_pressed_) {
+			emit clicked();
+			is_pressed_ = false;
+		}
+	}
+
+signals:
+	void clicked();
+
+private:
+	QLabel* txt_ = {};
+	QPixmap pixmap_ = {};
+	int font_sz_ = {};
+	QColor bk_color_ = {};
+	QColor txt_color_ = {};
+	bool is_pressed_ = false;
+	bool is_highlighted_ = false;
+};
+
+}
+}
diff --git a/test/qt_test/qt/signal_slot.h b/test/qt_test/qt/signal_slot.h
new file mode 100644
index 0000000..8f905fc
--- /dev/null
+++ b/test/qt_test/qt/signal_slot.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include <QObject>
+
+//#define DEFINE_SIGNAL(f) signals:void sig_##f; public void connect_to_sigslot_##f;
+
+#define CONNECT_SIG_SLOT(f) connect(this, SIGNAL(sig_##f), obj, SLOT(slot_##f));
diff --git a/test/qt_test/qt_test.cpp b/test/qt_test/qt_test.cpp
index a0490d5..f251778 100644
--- a/test/qt_test/qt_test.cpp
+++ b/test/qt_test/qt_test.cpp
@@ -2,21 +2,21 @@
 #include <qlayout.h>
 
 #include "../../jlib/log2.h"
-#include "../../jlib/qt/ErrorCode.h"
-#include "../../jlib/qt/QtDebug.h"
-#include "../../jlib/qt/QtDebugOutput.h"
-#include "../../jlib/qt/QtPathHelper.h"
-#include "../../jlib/qt/QtStylesheet.h"
-#include "../../jlib/qt/QtUtils.h"
-#include "../../jlib/qt/Ctrl/ThreadCtrl.h"
-#include "../../jlib/qt/Model/ThreadModel.h"
-#include "../../jlib/qt/View/BgColorBtn.h"
-#include "../../jlib/qt/View/HttpDlg.h"
-#include "../../jlib/qt/View/HttpDlgErrorCode.h"
-#include "../../jlib/qt/View/IconBtn.h"
-#include "../../jlib/qt/View/LoadingView.h"
-#include "../../jlib/qt/View/PageTitle.h"
-#include "../../jlib/qt/View/RndButton.h"
+#include "qt/ErrorCode.h"
+#include "qt/QtDebug.h"
+#include "qt/QtDebugOutput.h"
+#include "qt/QtPathHelper.h"
+#include "qt/QtStylesheet.h"
+#include "qt/QtUtils.h"
+#include "qt/Ctrl/ThreadCtrl.h"
+#include "qt/Model/ThreadModel.h"
+#include "qt/View/BgColorBtn.h"
+#include "qt/View/HttpDlg.h"
+#include "qt/View/HttpDlgErrorCode.h"
+#include "qt/View/IconBtn.h"
+#include "qt/View/LoadingView.h"
+#include "qt/View/PageTitle.h"
+#include "qt/View/RndButton.h"
 
 using namespace jlib::qt;
 
diff --git a/test/qt_test/qt_test.vcxproj b/test/qt_test/qt_test.vcxproj
index e188cec..b39099f 100644
--- a/test/qt_test/qt_test.vcxproj
+++ b/test/qt_test/qt_test.vcxproj
@@ -67,6 +67,7 @@
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
       <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType>
+      <AdditionalIncludeDirectories>$(DEVLIBS)\jlib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -88,6 +89,9 @@
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
+    <ClCompile Include="..\..\jlib\3rdparty\json\jsoncpp\json_reader.cpp" />
+    <ClCompile Include="..\..\jlib\3rdparty\json\jsoncpp\json_value.cpp" />
+    <ClCompile Include="..\..\jlib\3rdparty\json\jsoncpp\json_writer.cpp" />
     <ClCompile Include="main.cpp" />
     <ClCompile Include="qt_test.cpp" />
   </ItemGroup>
@@ -101,26 +105,23 @@
     <QtRcc Include="qt_test.qrc" />
   </ItemGroup>
   <ItemGroup>
-    <QtMoc Include="..\..\jlib\qt\View\BgColorBtn.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <QtMoc Include="..\..\jlib\qt\View\HttpDlg.h" />
-  </ItemGroup>
-  <ItemGroup>
-    <ClInclude Include="..\..\jlib\qt\Model\ThreadModel.h" />
-    <QtMoc Include="..\..\jlib\qt\Ctrl\ThreadCtrl.h" />
-    <ClInclude Include="..\..\jlib\qt\ErrorCode.h" />
-    <ClInclude Include="..\..\jlib\qt\QtDebug.h" />
-    <ClInclude Include="..\..\jlib\qt\QtDebugOutput.h" />
-    <ClInclude Include="..\..\jlib\qt\QtPathHelper.h" />
-    <ClInclude Include="..\..\jlib\qt\QtStylesheet.h" />
-    <ClInclude Include="..\..\jlib\qt\QtUtils.h" />
-    <ClInclude Include="..\..\jlib\qt\signal_slot.h" />
-    <ClInclude Include="..\..\jlib\qt\View\HttpDlgErrorCode.h" />
-    <QtMoc Include="..\..\jlib\qt\View\RndButton.h" />
-    <QtMoc Include="..\..\jlib\qt\View\PageTitle.h" />
-    <QtMoc Include="..\..\jlib\qt\View\LoadingView.h" />
-    <QtMoc Include="..\..\jlib\qt\View\IconBtn.h" />
+    <ClInclude Include="..\..\jlib\3rdparty\json\jsoncpp\json.h" />
+    <ClInclude Include="qt\ErrorCode.h" />
+    <ClInclude Include="qt\Model\ThreadModel.h" />
+    <ClInclude Include="qt\QtDebug.h" />
+    <ClInclude Include="qt\QtDebugOutput.h" />
+    <ClInclude Include="qt\QtPathHelper.h" />
+    <ClInclude Include="qt\QtStylesheet.h" />
+    <ClInclude Include="qt\QtUtils.h" />
+    <ClInclude Include="qt\signal_slot.h" />
+    <ClInclude Include="qt\View\HttpDlgErrorCode.h" />
+    <QtMoc Include="qt\View\RndButton.h" />
+    <QtMoc Include="qt\View\PageTitle.h" />
+    <QtMoc Include="qt\View\LoadingView.h" />
+    <QtMoc Include="qt\View\IconBtn.h" />
+    <QtMoc Include="qt\View\HttpDlg.h" />
+    <QtMoc Include="qt\View\BgColorBtn.h" />
+    <QtMoc Include="qt\Ctrl\ThreadCtrl.h" />
   </ItemGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
   <ImportGroup Condition="Exists('$(QtMsBuild)\qt.targets')">
diff --git a/test/qt_test/qt_test.vcxproj.filters b/test/qt_test/qt_test.vcxproj.filters
index a2c579d..d812af5 100644
--- a/test/qt_test/qt_test.vcxproj.filters
+++ b/test/qt_test/qt_test.vcxproj.filters
@@ -35,6 +35,9 @@
     <Filter Include="jlib_qt\Model">
       <UniqueIdentifier>{3e5f6680-de77-46c4-a80f-9a6ce7715eb7}</UniqueIdentifier>
     </Filter>
+    <Filter Include="jsoncpp">
+      <UniqueIdentifier>{0ea00850-28a6-45f9-af68-6c656c3572f1}</UniqueIdentifier>
+    </Filter>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="main.cpp">
@@ -43,31 +46,40 @@
     <ClCompile Include="qt_test.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\jlib\3rdparty\json\jsoncpp\json_reader.cpp">
+      <Filter>jsoncpp</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\jlib\3rdparty\json\jsoncpp\json_value.cpp">
+      <Filter>jsoncpp</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\jlib\3rdparty\json\jsoncpp\json_writer.cpp">
+      <Filter>jsoncpp</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <QtMoc Include="qt_test.h">
       <Filter>Header Files</Filter>
     </QtMoc>
-    <QtMoc Include="..\..\jlib\qt\View\BgColorBtn.h">
-      <Filter>jlib_qt\View</Filter>
+    <QtMoc Include="qt\Ctrl\ThreadCtrl.h">
+      <Filter>jlib_qt\Ctrl</Filter>
     </QtMoc>
-    <QtMoc Include="..\..\jlib\qt\View\HttpDlg.h">
+    <QtMoc Include="qt\View\BgColorBtn.h">
       <Filter>jlib_qt\View</Filter>
     </QtMoc>
-    <QtMoc Include="..\..\jlib\qt\View\IconBtn.h">
+    <QtMoc Include="qt\View\HttpDlg.h">
       <Filter>jlib_qt\View</Filter>
     </QtMoc>
-    <QtMoc Include="..\..\jlib\qt\View\LoadingView.h">
+    <QtMoc Include="qt\View\IconBtn.h">
       <Filter>jlib_qt\View</Filter>
     </QtMoc>
-    <QtMoc Include="..\..\jlib\qt\View\PageTitle.h">
+    <QtMoc Include="qt\View\LoadingView.h">
       <Filter>jlib_qt\View</Filter>
     </QtMoc>
-    <QtMoc Include="..\..\jlib\qt\View\RndButton.h">
+    <QtMoc Include="qt\View\PageTitle.h">
       <Filter>jlib_qt\View</Filter>
     </QtMoc>
-    <QtMoc Include="..\..\jlib\qt\Ctrl\ThreadCtrl.h">
-      <Filter>jlib_qt\Ctrl</Filter>
+    <QtMoc Include="qt\View\RndButton.h">
+      <Filter>jlib_qt\View</Filter>
     </QtMoc>
   </ItemGroup>
   <ItemGroup>
@@ -81,32 +93,35 @@
     </QtRcc>
   </ItemGroup>
   <ItemGroup>
-    <ClInclude Include="..\..\jlib\qt\View\HttpDlgErrorCode.h">
+    <ClInclude Include="..\..\jlib\3rdparty\json\jsoncpp\json.h">
+      <Filter>jsoncpp</Filter>
+    </ClInclude>
+    <ClInclude Include="qt\Model\ThreadModel.h">
+      <Filter>jlib_qt\Model</Filter>
+    </ClInclude>
+    <ClInclude Include="qt\View\HttpDlgErrorCode.h">
       <Filter>jlib_qt\View</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\jlib\qt\ErrorCode.h">
+    <ClInclude Include="qt\ErrorCode.h">
       <Filter>jlib_qt</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\jlib\qt\QtDebug.h">
+    <ClInclude Include="qt\QtDebug.h">
       <Filter>jlib_qt</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\jlib\qt\QtDebugOutput.h">
+    <ClInclude Include="qt\QtDebugOutput.h">
       <Filter>jlib_qt</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\jlib\qt\QtPathHelper.h">
+    <ClInclude Include="qt\QtPathHelper.h">
       <Filter>jlib_qt</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\jlib\qt\QtStylesheet.h">
+    <ClInclude Include="qt\QtStylesheet.h">
       <Filter>jlib_qt</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\jlib\qt\QtUtils.h">
+    <ClInclude Include="qt\QtUtils.h">
       <Filter>jlib_qt</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\jlib\qt\signal_slot.h">
+    <ClInclude Include="qt\signal_slot.h">
       <Filter>jlib_qt</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\jlib\qt\Model\ThreadModel.h">
-      <Filter>jlib_qt\Model</Filter>
-    </ClInclude>
   </ItemGroup>
 </Project>
\ No newline at end of file
diff --git a/test/test_ping/test_ping.cpp b/test/test_ping/test_ping.cpp
index d7fe966..45c53e5 100644
--- a/test/test_ping/test_ping.cpp
+++ b/test/test_ping/test_ping.cpp
@@ -1,7 +1,7 @@
 
 #include "../../jlib/base/config.h"
-#include <stdio.h>
 #include "../../jlib/net.h"
+#include <stdio.h>
 
 
 int main(int argc, char** argv)
-- 
2.18.1