From 2778431121e4ee2560c1f84daee1d759e57f0b26 Mon Sep 17 00:00:00 2001 From: Kane Wang Date: Fri, 6 Mar 2020 11:43:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8A=A0=E5=85=A5=E7=99=BB=E5=BD=95=E7=AA=97?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../car_dealer_util/car_dealer_util.vcxproj | 5 + .../car_dealer_util.vcxproj.filters | 12 + .../Widgets/LoginWidget/moc_QLoginDialog.cpp | 132 ++++++++ .../Widgets/LoginWidget/ui_QLoginDialog.h | 194 ++++++++++++ .../oracle/ImportToOracle.cpp | 11 +- 代码/cpp/car_dealer_util/source/main.cpp | 32 +- .../widgets/LoginWidget/QLoginDialog.cpp | 33 ++ .../source/widgets/LoginWidget/QLoginDialog.h | 22 ++ .../widgets/LoginWidget/QLoginDialog.ui | 281 ++++++++++++++++++ 9 files changed, 714 insertions(+), 8 deletions(-) create mode 100644 代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/source/Widgets/LoginWidget/moc_QLoginDialog.cpp create mode 100644 代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/source/Widgets/LoginWidget/ui_QLoginDialog.h create mode 100644 代码/cpp/car_dealer_util/source/widgets/LoginWidget/QLoginDialog.cpp create mode 100644 代码/cpp/car_dealer_util/source/widgets/LoginWidget/QLoginDialog.h create mode 100644 代码/cpp/car_dealer_util/source/widgets/LoginWidget/QLoginDialog.ui diff --git a/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj b/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj index e40b5c1..638eb8e 100644 --- a/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj +++ b/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj @@ -28,12 +28,14 @@ + + @@ -50,6 +52,7 @@ + {B12702AD-ABFB-343A-A199-8E24837244A3} @@ -125,6 +128,7 @@ stdafx.h $(IntDir)$(TargetName).pch /utf-8 %(AdditionalOptions) + ..\..\..\source\widgets\LoginWidget;%(AdditionalIncludeDirectories) Console @@ -152,6 +156,7 @@ stdafx.h $(IntDir)$(TargetName).pch /utf-8 %(AdditionalOptions) + ..\..\..\source\widgets\LoginWidget;%(AdditionalIncludeDirectories) Windows diff --git a/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj.filters b/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj.filters index 3558515..fc0249a 100644 --- a/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj.filters +++ b/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/car_dealer_util.vcxproj.filters @@ -71,6 +71,9 @@ {e5f3c3be-5fe7-471e-8dc7-d5889f5f87d9} + + {4aafaac0-1c39-407d-9701-175ad2e441c2} + @@ -109,6 +112,9 @@ 数据库\ocilib + + 窗口\登录窗口 + @@ -119,11 +125,17 @@ 窗口\主窗口 + + 窗口\登录窗口 + 窗口\主窗口 + + 窗口\登录窗口 + diff --git a/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/source/Widgets/LoginWidget/moc_QLoginDialog.cpp b/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/source/Widgets/LoginWidget/moc_QLoginDialog.cpp new file mode 100644 index 0000000..4c21819 --- /dev/null +++ b/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/source/Widgets/LoginWidget/moc_QLoginDialog.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'QLoginDialog.h' +** +** Created by: The Qt Meta Object Compiler version 67 (Qt 5.13.1) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include +#include "../../../../../../source/widgets/LoginWidget/QLoginDialog.h" +#include +#include +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'QLoginDialog.h' doesn't include ." +#elif Q_MOC_OUTPUT_REVISION != 67 +#error "This file was generated using the moc from 5.13.1. 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_QLoginDialog_t { + QByteArrayData data[6]; + 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_QLoginDialog_t, stringdata0) + ofs \ + - idx * sizeof(QByteArrayData)) \ + ) +static const qt_meta_stringdata_QLoginDialog_t qt_meta_stringdata_QLoginDialog = { + { +QT_MOC_LITERAL(0, 0, 12), // "QLoginDialog" +QT_MOC_LITERAL(1, 13, 4), // "init" +QT_MOC_LITERAL(2, 18, 0), // "" +QT_MOC_LITERAL(3, 19, 8), // "initData" +QT_MOC_LITERAL(4, 28, 10), // "initSignal" +QT_MOC_LITERAL(5, 39, 11) // "initWidgets" + + }, + "QLoginDialog\0init\0\0initData\0initSignal\0" + "initWidgets" +}; +#undef QT_MOC_LITERAL + +static const uint qt_meta_data_QLoginDialog[] = { + + // content: + 8, // revision + 0, // classname + 0, 0, // classinfo + 4, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + // slots: name, argc, parameters, tag, flags + 1, 0, 34, 2, 0x09 /* Protected */, + 3, 0, 35, 2, 0x09 /* Protected */, + 4, 0, 36, 2, 0x09 /* Protected */, + 5, 0, 37, 2, 0x09 /* Protected */, + + // slots: parameters + QMetaType::Void, + QMetaType::Void, + QMetaType::Void, + QMetaType::Void, + + 0 // eod +}; + +void QLoginDialog::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) +{ + if (_c == QMetaObject::InvokeMetaMethod) { + auto *_t = static_cast(_o); + Q_UNUSED(_t) + switch (_id) { + case 0: _t->init(); break; + case 1: _t->initData(); break; + case 2: _t->initSignal(); break; + case 3: _t->initWidgets(); break; + default: ; + } + } + Q_UNUSED(_a); +} + +QT_INIT_METAOBJECT const QMetaObject QLoginDialog::staticMetaObject = { { + &QDialog::staticMetaObject, + qt_meta_stringdata_QLoginDialog.data, + qt_meta_data_QLoginDialog, + qt_static_metacall, + nullptr, + nullptr +} }; + + +const QMetaObject *QLoginDialog::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject; +} + +void *QLoginDialog::qt_metacast(const char *_clname) +{ + if (!_clname) return nullptr; + if (!strcmp(_clname, qt_meta_stringdata_QLoginDialog.stringdata0)) + return static_cast(this); + return QDialog::qt_metacast(_clname); +} + +int QLoginDialog::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 < 4) + qt_static_metacall(this, _c, _id, _a); + _id -= 4; + } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) { + if (_id < 4) + *reinterpret_cast(_a[0]) = -1; + _id -= 4; + } + return _id; +} +QT_WARNING_POP +QT_END_MOC_NAMESPACE diff --git a/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/source/Widgets/LoginWidget/ui_QLoginDialog.h b/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/source/Widgets/LoginWidget/ui_QLoginDialog.h new file mode 100644 index 0000000..3134ae4 --- /dev/null +++ b/代码/cpp/car_dealer_util/proj/vs2019/car_dealer_util/source/Widgets/LoginWidget/ui_QLoginDialog.h @@ -0,0 +1,194 @@ +/******************************************************************************** +** Form generated from reading UI file 'QLoginDialog.ui' +** +** Created by: Qt User Interface Compiler version 5.13.1 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_QLOGINDIALOG_H +#define UI_QLOGINDIALOG_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_QLoginDialog +{ +public: + QWidget *widget; + QVBoxLayout *pLayoutMain; + QHBoxLayout *horizontalLayout; + QLabel *label; + QGroupBox *groupBox; + QGridLayout *gridLayout; + QLabel *label_2; + QLineEdit *lineEdit; + QLabel *label_3; + QLineEdit *lineEdit_2; + QLabel *label_4; + QLineEdit *lineEdit_3; + QHBoxLayout *horizontalLayout_2; + QSpacerItem *horizontalSpacer; + QToolButton *pButtonExit; + QToolButton *pButtonOK; + + void setupUi(QDialog *QLoginDialog) + { + if (QLoginDialog->objectName().isEmpty()) + QLoginDialog->setObjectName(QString::fromUtf8("QLoginDialog")); + QLoginDialog->resize(350, 160); + QLoginDialog->setMinimumSize(QSize(350, 160)); + QLoginDialog->setMaximumSize(QSize(350, 160)); + widget = new QWidget(QLoginDialog); + widget->setObjectName(QString::fromUtf8("widget")); + widget->setGeometry(QRect(0, 0, 349, 158)); + pLayoutMain = new QVBoxLayout(widget); + pLayoutMain->setSpacing(6); + pLayoutMain->setContentsMargins(11, 11, 11, 11); + pLayoutMain->setObjectName(QString::fromUtf8("pLayoutMain")); + pLayoutMain->setContentsMargins(5, 5, 5, 5); + horizontalLayout = new QHBoxLayout(); + horizontalLayout->setSpacing(6); + horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout")); + label = new QLabel(widget); + label->setObjectName(QString::fromUtf8("label")); + label->setPixmap(QPixmap(QString::fromUtf8(":/QMainFrame/Resources/cat.png"))); + + horizontalLayout->addWidget(label); + + groupBox = new QGroupBox(widget); + groupBox->setObjectName(QString::fromUtf8("groupBox")); + gridLayout = new QGridLayout(groupBox); + gridLayout->setSpacing(6); + gridLayout->setContentsMargins(11, 11, 11, 11); + gridLayout->setObjectName(QString::fromUtf8("gridLayout")); + label_2 = new QLabel(groupBox); + label_2->setObjectName(QString::fromUtf8("label_2")); + label_2->setMinimumSize(QSize(85, 0)); + label_2->setMaximumSize(QSize(85, 16777215)); + label_2->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout->addWidget(label_2, 0, 0, 1, 1); + + lineEdit = new QLineEdit(groupBox); + lineEdit->setObjectName(QString::fromUtf8("lineEdit")); + lineEdit->setMinimumSize(QSize(120, 0)); + lineEdit->setMaximumSize(QSize(120, 16777215)); + lineEdit->setStyleSheet(QString::fromUtf8("border: 1px solid silver;")); + lineEdit->setAlignment(Qt::AlignCenter); + lineEdit->setReadOnly(true); + + gridLayout->addWidget(lineEdit, 0, 1, 1, 1); + + label_3 = new QLabel(groupBox); + label_3->setObjectName(QString::fromUtf8("label_3")); + label_3->setMinimumSize(QSize(85, 0)); + label_3->setMaximumSize(QSize(85, 16777215)); + label_3->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout->addWidget(label_3, 1, 0, 1, 1); + + lineEdit_2 = new QLineEdit(groupBox); + lineEdit_2->setObjectName(QString::fromUtf8("lineEdit_2")); + lineEdit_2->setMinimumSize(QSize(120, 0)); + lineEdit_2->setMaximumSize(QSize(120, 16777215)); + lineEdit_2->setStyleSheet(QString::fromUtf8("border: 1px solid silver;")); + lineEdit_2->setAlignment(Qt::AlignCenter); + lineEdit_2->setReadOnly(true); + + gridLayout->addWidget(lineEdit_2, 1, 1, 1, 1); + + label_4 = new QLabel(groupBox); + label_4->setObjectName(QString::fromUtf8("label_4")); + label_4->setMinimumSize(QSize(85, 0)); + label_4->setMaximumSize(QSize(85, 16777215)); + label_4->setAlignment(Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter); + + gridLayout->addWidget(label_4, 2, 0, 1, 1); + + lineEdit_3 = new QLineEdit(groupBox); + lineEdit_3->setObjectName(QString::fromUtf8("lineEdit_3")); + lineEdit_3->setMinimumSize(QSize(120, 0)); + lineEdit_3->setMaximumSize(QSize(120, 16777215)); + lineEdit_3->setStyleSheet(QString::fromUtf8("border: 1px solid silver;")); + lineEdit_3->setAlignment(Qt::AlignCenter); + lineEdit_3->setReadOnly(true); + + gridLayout->addWidget(lineEdit_3, 2, 1, 1, 1); + + + horizontalLayout->addWidget(groupBox); + + + pLayoutMain->addLayout(horizontalLayout); + + horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->setSpacing(6); + horizontalLayout_2->setObjectName(QString::fromUtf8("horizontalLayout_2")); + horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); + + horizontalLayout_2->addItem(horizontalSpacer); + + pButtonExit = new QToolButton(widget); + pButtonExit->setObjectName(QString::fromUtf8("pButtonExit")); + QIcon icon; + icon.addFile(QString::fromUtf8(":/QMainFrame/Resources/quit.png"), QSize(), QIcon::Normal, QIcon::On); + pButtonExit->setIcon(icon); + pButtonExit->setIconSize(QSize(32, 32)); + pButtonExit->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + + horizontalLayout_2->addWidget(pButtonExit); + + pButtonOK = new QToolButton(widget); + pButtonOK->setObjectName(QString::fromUtf8("pButtonOK")); + QIcon icon1; + icon1.addFile(QString::fromUtf8(":/QMainFrame/Resources/ok.png"), QSize(), QIcon::Normal, QIcon::On); + pButtonOK->setIcon(icon1); + pButtonOK->setIconSize(QSize(32, 32)); + pButtonOK->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + + horizontalLayout_2->addWidget(pButtonOK); + + + pLayoutMain->addLayout(horizontalLayout_2); + + + retranslateUi(QLoginDialog); + + QMetaObject::connectSlotsByName(QLoginDialog); + } // setupUi + + void retranslateUi(QDialog *QLoginDialog) + { + QLoginDialog->setWindowTitle(QCoreApplication::translate("QLoginDialog", "\347\214\234\347\214\234\344\275\240\346\230\257\350\260\201~~~~", nullptr)); + label->setText(QString()); + groupBox->setTitle(QCoreApplication::translate("QLoginDialog", "\344\272\272\345\221\230\344\277\241\346\201\257\357\274\232", nullptr)); + label_2->setText(QCoreApplication::translate("QLoginDialog", "\347\263\273\347\273\237\347\224\250\346\210\267\345\220\215\357\274\232", nullptr)); + label_3->setText(QCoreApplication::translate("QLoginDialog", "\344\272\272\345\221\230\345\220\215\347\247\260\357\274\232", nullptr)); + label_4->setText(QCoreApplication::translate("QLoginDialog", "\345\262\227\344\275\215\357\274\232", nullptr)); + pButtonExit->setText(QCoreApplication::translate("QLoginDialog", "\351\200\200\345\207\272", nullptr)); + pButtonOK->setText(QCoreApplication::translate("QLoginDialog", "\347\241\256\350\256\244", nullptr)); + } // retranslateUi + +}; + +namespace Ui { + class QLoginDialog: public Ui_QLoginDialog {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_QLOGINDIALOG_H diff --git a/代码/cpp/car_dealer_util/source/Data/DataManipulation/oracle/ImportToOracle.cpp b/代码/cpp/car_dealer_util/source/Data/DataManipulation/oracle/ImportToOracle.cpp index 91557ba..006cf47 100644 --- a/代码/cpp/car_dealer_util/source/Data/DataManipulation/oracle/ImportToOracle.cpp +++ b/代码/cpp/car_dealer_util/source/Data/DataManipulation/oracle/ImportToOracle.cpp @@ -154,10 +154,15 @@ void ImportCarDealerAchievementToOracle( std::string use OCI_Prepare( pStatement, szSqlImport ); for ( auto iterAchievement = achievementVector.begin(); - iterAchievement != achievementVector.end(); - ++iterAchievement ) + iterAchievement != achievementVector.end(); + ++iterAchievement ) { - + string checkedAchievement = QString( "%1" ).arg( static_cast(iterAchievement->getCheckedAchievement()) ).toStdString(); + string policyAmount = QString( "%1" ).arg( iterAchievement->getPolicyAmount() ).toStdString(); + string cpicAmount = QString( "%1" ).arg( iterAchievement->getCpicAmount() ).toStdString(); + string piccAmount = QString( "%1" ).arg( iterAchievement->getPiccAmount() ).toStdString(); + string pinganAmount = QString( "%1" ).arg( iterAchievement->getPinganAmount() ).toStdString(); + string othersAmount = QString( "%1" ).arg( iterAchievement->getOthersAmount() ).toStdString(); } } diff --git a/代码/cpp/car_dealer_util/source/main.cpp b/代码/cpp/car_dealer_util/source/main.cpp index e71eb52..338a48a 100644 --- a/代码/cpp/car_dealer_util/source/main.cpp +++ b/代码/cpp/car_dealer_util/source/main.cpp @@ -1,13 +1,18 @@ #include #include +#include #include "Widgets/MainFrame/QMainFrame.h" +#include "QLoginDialog.h" #include "test/test.h" +using namespace std; + int main( int argc, char * argv[] ) { - QApplication * pApp = nullptr; - QMainFrame * pMainFrame = nullptr; - int returnCode = -1; + QApplication * pApp = nullptr; + QMainFrame * pMainFrame = nullptr; + QLoginDialog * pLoginDialog = nullptr; + int returnCode = -1; try { @@ -22,10 +27,27 @@ int main( int argc, char * argv[] ) return -1; } - test(); + //test(); + + //return 1; + + try + { + pLoginDialog = new QLoginDialog(); + + pLoginDialog->exec(); + } + catch ( std::runtime_error error ) + { + QMessageBox::critical( nullptr, + "错误!", + error.what() ); + + return -1; + } return 1; - + try { pMainFrame = new QMainFrame(); diff --git a/代码/cpp/car_dealer_util/source/widgets/LoginWidget/QLoginDialog.cpp b/代码/cpp/car_dealer_util/source/widgets/LoginWidget/QLoginDialog.cpp new file mode 100644 index 0000000..40ef3b2 --- /dev/null +++ b/代码/cpp/car_dealer_util/source/widgets/LoginWidget/QLoginDialog.cpp @@ -0,0 +1,33 @@ +#include "QLoginDialog.h" + +QLoginDialog::QLoginDialog( QWidget * parent ) + : QDialog( parent ) +{ + ui.setupUi( this ); + + init(); +} + +QLoginDialog::~QLoginDialog() +{ +} + +void QLoginDialog::init() +{ + initData(); + initWidgets(); + initSignal(); +} + +void QLoginDialog::initData() +{ +} + +void QLoginDialog::initSignal() +{ +} + +void QLoginDialog::initWidgets() +{ + setLayout( ui.pLayoutMain ); +} diff --git a/代码/cpp/car_dealer_util/source/widgets/LoginWidget/QLoginDialog.h b/代码/cpp/car_dealer_util/source/widgets/LoginWidget/QLoginDialog.h new file mode 100644 index 0000000..96adb20 --- /dev/null +++ b/代码/cpp/car_dealer_util/source/widgets/LoginWidget/QLoginDialog.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include "ui_QLoginDialog.h" + +class QLoginDialog : public QDialog +{ + Q_OBJECT + +public: + QLoginDialog(QWidget *parent = Q_NULLPTR); + ~QLoginDialog(); + +protected Q_SLOTS: + void init(); + void initData(); + void initSignal(); + void initWidgets(); + +private: + Ui::QLoginDialog ui; +}; diff --git a/代码/cpp/car_dealer_util/source/widgets/LoginWidget/QLoginDialog.ui b/代码/cpp/car_dealer_util/source/widgets/LoginWidget/QLoginDialog.ui new file mode 100644 index 0000000..9f45d66 --- /dev/null +++ b/代码/cpp/car_dealer_util/source/widgets/LoginWidget/QLoginDialog.ui @@ -0,0 +1,281 @@ + + + QLoginDialog + + + + 0 + 0 + 350 + 160 + + + + + 350 + 160 + + + + + 350 + 160 + + + + 猜猜你是谁~~~~ + + + + + 0 + 0 + 349 + 158 + + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + + + + + + :/QMainFrame/Resources/cat.png + + + + + + + 人员信息: + + + + + + + 85 + 0 + + + + + 85 + 16777215 + + + + 系统用户名: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 120 + 0 + + + + + 120 + 16777215 + + + + border: 1px solid silver; + + + Qt::AlignCenter + + + true + + + + + + + + 85 + 0 + + + + + 85 + 16777215 + + + + 人员名称: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 120 + 0 + + + + + 120 + 16777215 + + + + border: 1px solid silver; + + + Qt::AlignCenter + + + true + + + + + + + + 85 + 0 + + + + + 85 + 16777215 + + + + 岗位: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 120 + 0 + + + + + 120 + 16777215 + + + + border: 1px solid silver; + + + Qt::AlignCenter + + + true + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 退出 + + + + :/QMainFrame/Resources/quit.png + + + + + 32 + 32 + + + + Qt::ToolButtonTextBesideIcon + + + + + + + 确认 + + + + :/QMainFrame/Resources/ok.png + + + + + 32 + 32 + + + + Qt::ToolButtonTextBesideIcon + + + + + + + + + + + + + +