From 83b5b10bbe98a9c6d267e07a18abba65f1e0013c Mon Sep 17 00:00:00 2001 From: johanneshilden Date: Thu, 5 Oct 2017 14:31:52 +0300 Subject: [PATCH 1/8] Add qtmaterialappbar stub files --- components/components.pro | 7 +++++-- components/qtmaterialappbar.cpp | 2 ++ components/qtmaterialappbar.h | 4 ++++ components/qtmaterialappbar_p.h | 4 ++++ 4 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 components/qtmaterialappbar.cpp create mode 100644 components/qtmaterialappbar.h create mode 100644 components/qtmaterialappbar_p.h diff --git a/components/components.pro b/components/components.pro index 021bd62..c9568bf 100644 --- a/components/components.pro +++ b/components/components.pro @@ -37,7 +37,8 @@ SOURCES = \ qtmaterialdialog_internal.cpp \ qtmaterialdialog.cpp \ qtmaterialdrawer_internal.cpp \ - qtmaterialdrawer.cpp + qtmaterialdrawer.cpp \ + qtmaterialappbar.cpp HEADERS = \ qtmaterialavatar_p.h \ qtmaterialavatar.h \ @@ -97,6 +98,8 @@ HEADERS = \ qtmaterialdialog.h \ qtmaterialdrawer_internal.h \ qtmaterialdrawer_p.h \ - qtmaterialdrawer.h + qtmaterialdrawer.h \ + qtmaterialappbar.h \ + qtmaterialappbar_p.h RESOURCES += \ resources.qrc diff --git a/components/qtmaterialappbar.cpp b/components/qtmaterialappbar.cpp new file mode 100644 index 0000000..4e67b5a --- /dev/null +++ b/components/qtmaterialappbar.cpp @@ -0,0 +1,2 @@ +#include "qtmaterialappbar.h" +#include "qtmaterialappbar_p.h" diff --git a/components/qtmaterialappbar.h b/components/qtmaterialappbar.h new file mode 100644 index 0000000..b2c8a20 --- /dev/null +++ b/components/qtmaterialappbar.h @@ -0,0 +1,4 @@ +#ifndef QTMATERIALAPPBAR_H +#define QTMATERIALAPPBAR_H + +#endif // QTMATERIALAPPBAR_H diff --git a/components/qtmaterialappbar_p.h b/components/qtmaterialappbar_p.h new file mode 100644 index 0000000..58f1d3c --- /dev/null +++ b/components/qtmaterialappbar_p.h @@ -0,0 +1,4 @@ +#ifndef QTMATERIALAPPBAR_P_H +#define QTMATERIALAPPBAR_P_H + +#endif // QTMATERIALAPPBAR_P_H From 1c7892d8b1cfa747615df8d2f2df94cdf98f6c0e Mon Sep 17 00:00:00 2001 From: Francesco Perillo Date: Thu, 5 Oct 2017 15:31:14 +0200 Subject: [PATCH 2/8] QtMaterialTextField: implemeted hiding of underscore --- components/qtmaterialtextfield.cpp | 31 ++++++++++++++++++++++------ components/qtmaterialtextfield.h | 1 + components/qtmaterialtextfield_p.h | 1 + examples/textfieldsettingseditor.cpp | 8 +++++++ examples/textfieldsettingseditor.h | 1 + examples/textfieldsettingsform.ui | 10 +++++++++ 6 files changed, 46 insertions(+), 6 deletions(-) diff --git a/components/qtmaterialtextfield.cpp b/components/qtmaterialtextfield.cpp index 86643d6..4e1a8a3 100644 --- a/components/qtmaterialtextfield.cpp +++ b/components/qtmaterialtextfield.cpp @@ -29,6 +29,7 @@ void QtMaterialTextFieldPrivate::init() label = 0; labelFontSize = 9.5; showLabel = false; + showUnderscore = true; useThemeColors = true; q->setFrame(false); @@ -231,6 +232,20 @@ QColor QtMaterialTextField::underlineColor() const } } +void QtMaterialTextField::setShowUnderscore(bool value) +{ + Q_D(QtMaterialTextField); + + if (d->showUnderscore == value) { + return; + } + + d->showUnderscore = value; + + update(); +} + + /*! * \reimp */ @@ -274,12 +289,15 @@ void QtMaterialTextField::paintEvent(QPaintEvent *event) const int y = height()-1; const int wd = width()-5; - QPen pen; - pen.setWidth(1); - pen.setColor(underlineColor()); - painter.setPen(pen); - painter.setOpacity(1); - painter.drawLine(2.5, y, wd, y); + + if( d->showUnderscore ) + { + QPen pen; + pen.setWidth(1); + pen.setColor(underlineColor()); + painter.setPen(pen); + painter.setOpacity(1); + painter.drawLine(2.5, y, wd, y); QBrush brush; brush.setStyle(Qt::SolidPattern); @@ -292,4 +310,5 @@ void QtMaterialTextField::paintEvent(QPaintEvent *event) const int w = (1-progress)*static_cast(wd/2); painter.drawRect(w+2.5, height()-2, wd-w*2, 2); } + } } diff --git a/components/qtmaterialtextfield.h b/components/qtmaterialtextfield.h index 81f740b..6622515 100644 --- a/components/qtmaterialtextfield.h +++ b/components/qtmaterialtextfield.h @@ -41,6 +41,7 @@ public: void setUnderlineColor(const QColor &color); QColor underlineColor() const; + void setShowUnderscore(bool value); protected: bool event(QEvent *event) Q_DECL_OVERRIDE; diff --git a/components/qtmaterialtextfield_p.h b/components/qtmaterialtextfield_p.h index ad4db28..7924a1d 100644 --- a/components/qtmaterialtextfield_p.h +++ b/components/qtmaterialtextfield_p.h @@ -29,6 +29,7 @@ public: QString labelString; qreal labelFontSize; bool showLabel; + bool showUnderscore; bool useThemeColors; }; diff --git a/examples/textfieldsettingseditor.cpp b/examples/textfieldsettingseditor.cpp index dcb7069..ddad14f 100644 --- a/examples/textfieldsettingseditor.cpp +++ b/examples/textfieldsettingseditor.cpp @@ -41,6 +41,7 @@ TextFieldSettingsEditor::TextFieldSettingsEditor(QWidget *parent) connect(ui->inkColorToolButton, SIGNAL(pressed()), this, SLOT(selectColor())); connect(ui->underlineColorToolButton, SIGNAL(pressed()), this, SLOT(selectColor())); connect(ui->labelColorToolButton, SIGNAL(pressed()), this, SLOT(selectColor())); + connect(ui->underscoreCheckBox, SIGNAL(toggled(bool)), this, SLOT(setShowUnderscore())); connect(m_textField, SIGNAL(textChanged(QString)), this, SLOT(setupForm())); } @@ -58,6 +59,7 @@ void TextFieldSettingsEditor::setupForm() ui->labelCheckBox->setChecked(m_textField->hasLabel()); ui->labelTextLineEdit->setText(m_textField->label()); ui->useThemeColorsCheckBox->setChecked(m_textField->useThemeColors()); + ui->underscoreCheckBox->setChecked( true ); } void TextFieldSettingsEditor::updateWidget() @@ -68,6 +70,7 @@ void TextFieldSettingsEditor::updateWidget() m_textField->setLabel(ui->labelTextLineEdit->text()); m_textField->setShowLabel(ui->labelCheckBox->isChecked()); m_textField->setUseThemeColors(ui->useThemeColorsCheckBox->isChecked()); + m_textField->setShowUnderscore(ui->underscoreCheckBox->isChecked()); } void TextFieldSettingsEditor::selectColor() @@ -92,3 +95,8 @@ void TextFieldSettingsEditor::selectColor() } setupForm(); } + +void TextFieldSettingsEditor::setShowUnderscore() +{ + m_textField->setShowUnderscore( ui->underscoreCheckBox->isChecked() ); +} diff --git a/examples/textfieldsettingseditor.h b/examples/textfieldsettingseditor.h index 21c69f5..ed5a3c2 100644 --- a/examples/textfieldsettingseditor.h +++ b/examples/textfieldsettingseditor.h @@ -18,6 +18,7 @@ protected slots: void setupForm(); void updateWidget(); void selectColor(); + void setShowUnderscore(); private: Ui::TextFieldSettingsForm *const ui; diff --git a/examples/textfieldsettingsform.ui b/examples/textfieldsettingsform.ui index 106c58c..9edac01 100644 --- a/examples/textfieldsettingsform.ui +++ b/examples/textfieldsettingsform.ui @@ -167,6 +167,16 @@ + + + + Underscore + + + + + + From b3b0f18be94f0293f979d066e6bd335e530813aa Mon Sep 17 00:00:00 2001 From: johanneshilden Date: Thu, 5 Oct 2017 17:11:41 +0300 Subject: [PATCH 3/8] Add AppBar files --- components/qtmaterialappbar.cpp | 137 ++++++++++++++++++++++++++++++++ components/qtmaterialappbar.h | 36 +++++++++ components/qtmaterialappbar_p.h | 22 +++++ 3 files changed, 195 insertions(+) diff --git a/components/qtmaterialappbar.cpp b/components/qtmaterialappbar.cpp index 4e67b5a..5e5e230 100644 --- a/components/qtmaterialappbar.cpp +++ b/components/qtmaterialappbar.cpp @@ -1,2 +1,139 @@ #include "qtmaterialappbar.h" #include "qtmaterialappbar_p.h" +#include +#include +#include +#include "lib/qtmaterialstyle.h" + +/*! + * \class QtMaterialAppBarPrivate + * \internal + */ + +/*! + * \internal + */ +QtMaterialAppBarPrivate::QtMaterialAppBarPrivate(QtMaterialAppBar *q) + : q_ptr(q) +{ +} + +/*! + * \internal + */ +QtMaterialAppBarPrivate::~QtMaterialAppBarPrivate() +{ +} + +/*! + * \internal + */ +void QtMaterialAppBarPrivate::init() +{ + Q_Q(QtMaterialAppBar); + + useThemeColors = true; + + QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect; + effect->setBlurRadius(11); + effect->setColor(QColor(0, 0, 0, 50)); + effect->setOffset(0, 3); + + q->setGraphicsEffect(effect); + + QHBoxLayout *layout = new QHBoxLayout; + q->setLayout(layout); +} + +/*! + * \class QtMaterialAppBar + */ + +QtMaterialAppBar::QtMaterialAppBar(QWidget *parent) + : QWidget(parent) +{ + d_func()->init(); +} + +QtMaterialAppBar::~QtMaterialAppBar() +{ +} + +QSize QtMaterialAppBar::sizeHint() const +{ + return QSize(-1, 64); +} + +void QtMaterialAppBar::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + QPainter painter(this); + + painter.fillRect(rect(), backgroundColor()); +} + +void QtMaterialAppBar::setUseThemeColors(bool value) +{ + Q_D(QtMaterialAppBar); + + if (d->useThemeColors == value) { + return; + } + + d->useThemeColors = value; + update(); +} + +bool QtMaterialAppBar::useThemeColors() const +{ + Q_D(const QtMaterialAppBar); + + return d->useThemeColors; +} + +void QtMaterialAppBar::setForegroundColor(const QColor &color) +{ + Q_D(QtMaterialAppBar); + + d->foregroundColor = color; + + if (d->useThemeColors == true) { + d->useThemeColors = false; + } + update(); +} + +QColor QtMaterialAppBar::foregroundColor() const +{ + Q_D(const QtMaterialAppBar); + + if (d->useThemeColors || !d->foregroundColor.isValid()) { + return QtMaterialStyle::instance().themeColor("primary1"); + } else { + return d->foregroundColor; + } +} + +void QtMaterialAppBar::setBackgroundColor(const QColor &color) +{ + Q_D(QtMaterialAppBar); + + d->backgroundColor = color; + + if (d->useThemeColors == true) { + d->useThemeColors = false; + } + update(); +} + +QColor QtMaterialAppBar::backgroundColor() const +{ + Q_D(const QtMaterialAppBar); + + if (d->useThemeColors || !d->backgroundColor.isValid()) { + return QtMaterialStyle::instance().themeColor("primary1"); + } else { + return d->backgroundColor; + } +} diff --git a/components/qtmaterialappbar.h b/components/qtmaterialappbar.h index b2c8a20..6558ccf 100644 --- a/components/qtmaterialappbar.h +++ b/components/qtmaterialappbar.h @@ -1,4 +1,40 @@ #ifndef QTMATERIALAPPBAR_H #define QTMATERIALAPPBAR_H +#include + +class QtMaterialAppBarPrivate; + +class QtMaterialAppBar : public QWidget +{ + Q_OBJECT + + Q_PROPERTY(QColor foregroundColor WRITE setForegroundColor READ foregroundColor) + Q_PROPERTY(QColor backgroundColor WRITE setBackgroundColor READ backgroundColor) + +public: + explicit QtMaterialAppBar(QWidget *parent = 0); + ~QtMaterialAppBar(); + + QSize sizeHint() const Q_DECL_OVERRIDE; + + void setUseThemeColors(bool value); + bool useThemeColors() const; + + void setForegroundColor(const QColor &color); + QColor foregroundColor() const; + + void setBackgroundColor(const QColor &color); + QColor backgroundColor() const; + +protected: + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; + + const QScopedPointer d_ptr; + +private: + Q_DISABLE_COPY(QtMaterialAppBar) + Q_DECLARE_PRIVATE(QtMaterialAppBar) +}; + #endif // QTMATERIALAPPBAR_H diff --git a/components/qtmaterialappbar_p.h b/components/qtmaterialappbar_p.h index 58f1d3c..0586556 100644 --- a/components/qtmaterialappbar_p.h +++ b/components/qtmaterialappbar_p.h @@ -1,4 +1,26 @@ #ifndef QTMATERIALAPPBAR_P_H #define QTMATERIALAPPBAR_P_H +#include +#include + +class QtMaterialAppBar; + +class QtMaterialAppBarPrivate +{ + Q_DISABLE_COPY(QtMaterialAppBarPrivate) + Q_DECLARE_PUBLIC(QtMaterialAppBar) + +public: + QtMaterialAppBarPrivate(QtMaterialAppBar *q); + ~QtMaterialAppBarPrivate(); + + void init(); + + QtMaterialAppBar *const q_ptr; + bool useThemeColors; + QColor foregroundColor; + QColor backgroundColor; +}; + #endif // QTMATERIALAPPBAR_P_H From 776e089399bc33cdc2fb1b596b0754af69be2c63 Mon Sep 17 00:00:00 2001 From: johanneshilden Date: Thu, 5 Oct 2017 17:35:22 +0300 Subject: [PATCH 4/8] Rename underscore to underline --- components/qtmaterialtextfield.cpp | 38 +++++++++++++++++------------- components/qtmaterialtextfield.h | 4 +++- components/qtmaterialtextfield_p.h | 2 +- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/components/qtmaterialtextfield.cpp b/components/qtmaterialtextfield.cpp index 4e1a8a3..97480c9 100644 --- a/components/qtmaterialtextfield.cpp +++ b/components/qtmaterialtextfield.cpp @@ -29,7 +29,7 @@ void QtMaterialTextFieldPrivate::init() label = 0; labelFontSize = 9.5; showLabel = false; - showUnderscore = true; + showUnderline = true; useThemeColors = true; q->setFrame(false); @@ -232,19 +232,24 @@ QColor QtMaterialTextField::underlineColor() const } } -void QtMaterialTextField::setShowUnderscore(bool value) +void QtMaterialTextField::setShowUnderline(bool value) { Q_D(QtMaterialTextField); - if (d->showUnderscore == value) { + if (d->showUnderline == value) { return; } - d->showUnderscore = value; - + d->showUnderline = value; update(); } +bool QtMaterialTextField::hasUnderline() const +{ + Q_D(const QtMaterialTextField); + + return d->showUnderline; +} /*! * \reimp @@ -289,8 +294,7 @@ void QtMaterialTextField::paintEvent(QPaintEvent *event) const int y = height()-1; const int wd = width()-5; - - if( d->showUnderscore ) + if (d->showUnderline) { QPen pen; pen.setWidth(1); @@ -299,16 +303,16 @@ void QtMaterialTextField::paintEvent(QPaintEvent *event) painter.setOpacity(1); painter.drawLine(2.5, y, wd, y); - QBrush brush; - brush.setStyle(Qt::SolidPattern); - brush.setColor(inkColor()); + QBrush brush; + brush.setStyle(Qt::SolidPattern); + brush.setColor(inkColor()); - if (progress > 0) - { - painter.setPen(Qt::NoPen); - painter.setBrush(brush); - const int w = (1-progress)*static_cast(wd/2); - painter.drawRect(w+2.5, height()-2, wd-w*2, 2); - } + if (progress > 0) + { + painter.setPen(Qt::NoPen); + painter.setBrush(brush); + const int w = (1-progress)*static_cast(wd/2); + painter.drawRect(w+2.5, height()-2, wd-w*2, 2); + } } } diff --git a/components/qtmaterialtextfield.h b/components/qtmaterialtextfield.h index 6622515..d4a12f6 100644 --- a/components/qtmaterialtextfield.h +++ b/components/qtmaterialtextfield.h @@ -41,7 +41,9 @@ public: void setUnderlineColor(const QColor &color); QColor underlineColor() const; - void setShowUnderscore(bool value); + + void setShowUnderline(bool value); + bool hasUnderline() const; protected: bool event(QEvent *event) Q_DECL_OVERRIDE; diff --git a/components/qtmaterialtextfield_p.h b/components/qtmaterialtextfield_p.h index 7924a1d..51d7cc1 100644 --- a/components/qtmaterialtextfield_p.h +++ b/components/qtmaterialtextfield_p.h @@ -29,7 +29,7 @@ public: QString labelString; qreal labelFontSize; bool showLabel; - bool showUnderscore; + bool showUnderline; bool useThemeColors; }; From 487643651bf8f49bab91c022dc0ec75cf6ff5e87 Mon Sep 17 00:00:00 2001 From: johanneshilden Date: Thu, 5 Oct 2017 17:39:01 +0300 Subject: [PATCH 5/8] Rename underscore to underline --- examples/textfieldsettingseditor.cpp | 10 +++++----- examples/textfieldsettingseditor.h | 2 +- examples/textfieldsettingsform.ui | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/examples/textfieldsettingseditor.cpp b/examples/textfieldsettingseditor.cpp index ddad14f..ce21cd1 100644 --- a/examples/textfieldsettingseditor.cpp +++ b/examples/textfieldsettingseditor.cpp @@ -41,7 +41,7 @@ TextFieldSettingsEditor::TextFieldSettingsEditor(QWidget *parent) connect(ui->inkColorToolButton, SIGNAL(pressed()), this, SLOT(selectColor())); connect(ui->underlineColorToolButton, SIGNAL(pressed()), this, SLOT(selectColor())); connect(ui->labelColorToolButton, SIGNAL(pressed()), this, SLOT(selectColor())); - connect(ui->underscoreCheckBox, SIGNAL(toggled(bool)), this, SLOT(setShowUnderscore())); + connect(ui->underlineCheckBox, SIGNAL(toggled(bool)), this, SLOT(setShowUnderline())); connect(m_textField, SIGNAL(textChanged(QString)), this, SLOT(setupForm())); } @@ -59,7 +59,7 @@ void TextFieldSettingsEditor::setupForm() ui->labelCheckBox->setChecked(m_textField->hasLabel()); ui->labelTextLineEdit->setText(m_textField->label()); ui->useThemeColorsCheckBox->setChecked(m_textField->useThemeColors()); - ui->underscoreCheckBox->setChecked( true ); + ui->underlineCheckBox->setChecked(m_textField->hasUnderline()); } void TextFieldSettingsEditor::updateWidget() @@ -70,7 +70,7 @@ void TextFieldSettingsEditor::updateWidget() m_textField->setLabel(ui->labelTextLineEdit->text()); m_textField->setShowLabel(ui->labelCheckBox->isChecked()); m_textField->setUseThemeColors(ui->useThemeColorsCheckBox->isChecked()); - m_textField->setShowUnderscore(ui->underscoreCheckBox->isChecked()); + m_textField->setShowUnderline(ui->underlineCheckBox->isChecked()); } void TextFieldSettingsEditor::selectColor() @@ -96,7 +96,7 @@ void TextFieldSettingsEditor::selectColor() setupForm(); } -void TextFieldSettingsEditor::setShowUnderscore() +void TextFieldSettingsEditor::setShowUnderline() { - m_textField->setShowUnderscore( ui->underscoreCheckBox->isChecked() ); + m_textField->setShowUnderline( ui->underlineCheckBox->isChecked() ); } diff --git a/examples/textfieldsettingseditor.h b/examples/textfieldsettingseditor.h index ed5a3c2..6631e27 100644 --- a/examples/textfieldsettingseditor.h +++ b/examples/textfieldsettingseditor.h @@ -18,7 +18,7 @@ protected slots: void setupForm(); void updateWidget(); void selectColor(); - void setShowUnderscore(); + void setShowUnderline(); private: Ui::TextFieldSettingsForm *const ui; diff --git a/examples/textfieldsettingsform.ui b/examples/textfieldsettingsform.ui index 9edac01..12e1c87 100644 --- a/examples/textfieldsettingsform.ui +++ b/examples/textfieldsettingsform.ui @@ -168,14 +168,14 @@ - + - Underscore + Underline - + From ed734c0f6ebaa60db6914d3cb5617fbfd8b1329b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Heikki=20Johannes=20Hild=C3=A9n?= Date: Thu, 5 Oct 2017 17:54:11 +0300 Subject: [PATCH 6/8] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d6f2499..2585e4b 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ I finally took the time to go through and clean up this code. The build includes - + From f7bc4349d57128d98bb4aed4730f0a7be8ca3fe4 Mon Sep 17 00:00:00 2001 From: johanneshilden Date: Thu, 5 Oct 2017 17:56:10 +0300 Subject: [PATCH 7/8] Center align gif anims in README --- README.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 2585e4b..1774c36 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ I finally took the time to go through and clean up this code. The build includes - + - @@ -44,7 +44,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -57,7 +57,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -70,7 +70,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -83,7 +83,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -96,7 +96,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -109,7 +109,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -122,7 +122,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -135,7 +135,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -148,7 +148,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -161,7 +161,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -174,7 +174,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -187,7 +187,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -200,7 +200,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -213,7 +213,7 @@ I finally took the time to go through and clean up this code. The build includes - @@ -226,7 +226,7 @@ I finally took the time to go through and clean up this code. The build includes - From a312f3db972c59939893c676949538c9805aad44 Mon Sep 17 00:00:00 2001 From: johanneshilden Date: Thu, 5 Oct 2017 17:57:28 +0300 Subject: [PATCH 8/8] Move drawer gif anim back to the left --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1774c36..c8d0daf 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ I finally took the time to go through and clean up this code. The build includes -
@@ -18,7 +18,7 @@ I finally took the time to go through and clean up this code. The build includes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+