Add experimental Auto Complete component

This commit is contained in:
johanneshilden 2017-10-13 00:27:50 +03:00
parent c0712f210a
commit 8248df4efb
10 changed files with 540 additions and 3 deletions

View File

@ -1,2 +1,203 @@
#include "qtmaterialautocomplete.h"
#include "qtmaterialautocomplete_p.h"
#include <QtWidgets/QGraphicsDropShadowEffect>
#include <QtWidgets/QVBoxLayout>
#include <QEvent>
#include "qtmaterialflatbutton.h"
QtMaterialAutoCompletePrivate::QtMaterialAutoCompletePrivate(QtMaterialAutoComplete *q)
: QtMaterialTextFieldPrivate(q)
{
}
QtMaterialAutoCompletePrivate::~QtMaterialAutoCompletePrivate()
{
}
void QtMaterialAutoCompletePrivate::init()
{
Q_Q(QtMaterialAutoComplete);
menu = new QWidget;
menuLayout = new QVBoxLayout;
maxWidth = 0;
menu->setParent(q->parentWidget());
QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect;
effect->setBlurRadius(11);
effect->setColor(QColor(0, 0, 0, 50));
effect->setOffset(0, 3);
menu->setGraphicsEffect(effect);
menu->setLayout(menuLayout);
menu->setVisible(false);
menuLayout->setContentsMargins(0, 0, 0, 0);
menuLayout->setSpacing(0);
QObject::connect(q, SIGNAL(textChanged(QString)), q, SLOT(updateResults(QString)));
//
QStringList states =
{ "Alabama"
, "Alaska"
, "American Samoa"
, "Arizona"
, "Arkansas"
, "California"
, "Colorado"
, "Connecticut"
, "Delaware"
, "District of Columbia"
, "Florida"
, "Georgia"
, "Guam"
, "Hawaii"
, "Idaho"
, "Illinois"
, "Indiana"
, "Iowa"
, "Kansas"
, "Kentucky"
, "Louisiana"
, "Maine"
, "Maryland"
, "Massachusetts"
, "Michigan"
, "Minnesota"
, "Mississippi"
, "Missouri"
, "Montana"
, "Nebraska"
, "Nevada"
, "New Hampshire"
, "New Jersey"
, "New Mexico"
, "New York"
, "North Carolina"
, "North Dakota"
, "Northern Marianas Islands"
, "Ohio"
, "Oklahoma"
, "Oregon"
, "Pennsylvania"
, "Puerto Rico"
, "Rhode Island"
, "South Carolina"
, "South Dakota"
, "Tennessee"
, "Texas"
, "Utah"
, "Vermont"
, "Virginia"
, "Virgin Islands"
, "Washington"
, "West Virginia"
, "Wisconsin"
, "Wyoming"
};
foreach (QString state, states) {
dataSource.push_back(state);
}
}
QtMaterialAutoComplete::QtMaterialAutoComplete(QWidget *parent)
: QtMaterialTextField(*new QtMaterialAutoCompletePrivate(this), parent)
{
d_func()->init();
}
QtMaterialAutoComplete::~QtMaterialAutoComplete()
{
}
void QtMaterialAutoComplete::updateResults(QString text)
{
Q_D(QtMaterialAutoComplete);
QStringList results;
QString trimmed(text.trimmed());
if (!trimmed.isEmpty()) {
QString lookup(trimmed.toLower());
QStringList::iterator i;
for (i = d->dataSource.begin(); i != d->dataSource.end(); ++i) {
if (i->toLower().startsWith(lookup)) {
results.push_back(*i);
}
}
}
const int diff = results.length() - d->menuLayout->count();
QFont font("Roboto", 12, QFont::Normal);
if (diff > 0) {
for (int c = 0; c < diff; c++) {
QtMaterialFlatButton *item = new QtMaterialFlatButton;
item->setFont(font);
item->setTextAlignment(Qt::AlignLeft);
item->setCornerRadius(0);
item->setHaloVisible(false);
item->setFixedHeight(50);
d->menuLayout->addWidget(item);
}
} else if (diff < 0) {
for (int c = 0; c < -diff; c++) {
QWidget *widget = d->menuLayout->itemAt(0)->widget();
if (widget) {
d->menuLayout->removeWidget(widget);
delete widget;
}
}
}
QFontMetrics *fm = new QFontMetrics(font);
d->maxWidth = 0;
for (int i = 0; i < results.count(); ++i) {
QWidget *widget = d->menuLayout->itemAt(i)->widget();
QtMaterialFlatButton *item;
if ((item = static_cast<QtMaterialFlatButton *>(widget))) {
QString text = results.at(i);
QRect rect = fm->boundingRect(text);
d->maxWidth = qMax(d->maxWidth, rect.width());
item->setText(text);
}
}
if (!results.count()) {
d->menu->hide();
} else if (d->menu->isHidden()) {
d->menu->show();
}
d->menu->setFixedHeight(results.length()*50);
d->menu->setFixedWidth(qMax(d->maxWidth + 24, width()));
d->menu->update();
}
bool QtMaterialAutoComplete::QtMaterialAutoComplete::event(QEvent *event)
{
Q_D(QtMaterialAutoComplete);
switch (event->type())
{
case QEvent::Move:
case QEvent::Resize: {
d->menu->move(pos() + QPoint(0, height() + 6));
break;
}
case QEvent::ParentChange: {
QWidget *widget = static_cast<QWidget *>(parent());
if (widget) {
d->menu->setParent(widget);
}
break;
}
default:
break;
}
return QtMaterialTextField::event(event);
}

View File

@ -1,4 +1,27 @@
#ifndef QTMATERIALAUTOCOMPLETE_H
#define QTMATERIALAUTOCOMPLETE_H
#include "qtmaterialtextfield.h"
class QtMaterialAutoCompletePrivate;
class QtMaterialAutoComplete : public QtMaterialTextField
{
Q_OBJECT
public:
explicit QtMaterialAutoComplete(QWidget *parent = 0);
~QtMaterialAutoComplete();
protected slots:
void updateResults(QString text);
protected:
bool event(QEvent *event) Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(QtMaterialAutoComplete)
Q_DECLARE_PRIVATE(QtMaterialAutoComplete)
};
#endif // QTMATERIALAUTOCOMPLETE_H

View File

@ -1,4 +1,27 @@
#ifndef QTMATERIALAUTOCOMPLETE_P_H
#define QTMATERIALAUTOCOMPLETE_P_H
#include "qtmaterialtextfield_p.h"
class QWidget;
class QVBoxLayout;
class QtMaterialAutoCompleteOverlay;
class QtMaterialAutoCompletePrivate : public QtMaterialTextFieldPrivate
{
Q_DISABLE_COPY(QtMaterialAutoCompletePrivate)
Q_DECLARE_PUBLIC(QtMaterialAutoComplete)
public:
QtMaterialAutoCompletePrivate(QtMaterialAutoComplete *q);
virtual ~QtMaterialAutoCompletePrivate();
void init();
QWidget *menu;
QVBoxLayout *menuLayout;
QStringList dataSource;
int maxWidth;
};
#endif // QTMATERIALAUTOCOMPLETE_P_H

View File

@ -248,6 +248,13 @@ bool QtMaterialTextField::hasInputLine() const
return d->showInputLine;
}
QtMaterialTextField::QtMaterialTextField(QtMaterialTextFieldPrivate &d, QWidget *parent)
: QLineEdit(parent),
d_ptr(&d)
{
d_func()->init();
}
/*!
* \reimp
*/

View File

@ -46,6 +46,8 @@ public:
bool hasInputLine() const;
protected:
QtMaterialTextField(QtMaterialTextFieldPrivate &d, QWidget *parent = 0);
bool event(QEvent *event) Q_DECL_OVERRIDE;
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;

View File

@ -15,7 +15,7 @@ class QtMaterialTextFieldPrivate
public:
QtMaterialTextFieldPrivate(QtMaterialTextField *q);
~QtMaterialTextFieldPrivate();
virtual ~QtMaterialTextFieldPrivate();
void init();

View File

@ -0,0 +1,212 @@
#include "autocompletesettingseditor.h"
#include <QVBoxLayout>
#include <QDebug>
#include <qtmaterialautocomplete.h>
#include <QPainter>
#include <QPushButton>
#include <QEvent>
#include "qtmaterialflatbutton.h"
#include <QtWidgets/QGraphicsDropShadowEffect>
AutoCompleteSettingsEditor::AutoCompleteSettingsEditor(QWidget *parent)
: QWidget(parent),
//ui(new Ui::AutoCompleteSettingsForm),
m_autocomplete(new QtMaterialAutoComplete)
{
QVBoxLayout *layout = new QVBoxLayout;
setLayout(layout);
QWidget *widget = new QWidget;
layout->addWidget(widget);
QWidget *canvas = new QWidget;
canvas->setStyleSheet("QWidget { background: white; }");
layout->addWidget(canvas);
//ui->setupUi(widget);
layout->setContentsMargins(20, 20, 20, 20);
layout = new QVBoxLayout;
canvas->setLayout(layout);
/*
Xyz *xyz = new Xyz(m_autocomplete);
xyz->setParent(canvas);
*/
//Menu *menu = new Menu;
//menu->setParent(xyz);
//menu->move(220, 140);
//menu->move(pos());
//qDebug() << menu->parentWidget()->mapFromGlobal(QPoint(0, 0));
//qDebug() << menu->mapToGlobal(QPoint(0, 0));
layout->addWidget(m_autocomplete);
layout->setAlignment(m_autocomplete, Qt::AlignCenter);
setupForm();
//m_autocomplete->installEventFilter(xyz);
}
AutoCompleteSettingsEditor::~AutoCompleteSettingsEditor()
{
//delete ui;
}
void AutoCompleteSettingsEditor::setupForm()
{
}
void AutoCompleteSettingsEditor::updateWidget()
{
}
void AutoCompleteSettingsEditor::selectColor()
{
}
// ----
Xyz::Xyz(QtMaterialAutoComplete *input, QWidget *parent)
: QtMaterialOverlayWidget(parent),
m_input(input),
m_menu(new Menu)
{
m_menu->setParent(this);
}
Xyz::~Xyz()
{
}
bool Xyz::eventFilter(QObject *obj, QEvent *event)
{
switch (event->type())
{
case QEvent::Move:
case QEvent::Resize: {
QtMaterialAutoComplete *widget = static_cast<QtMaterialAutoComplete *>(obj);
if (widget) {
m_menu->move(widget->pos() + QPoint(0, m_input->height() + 6));
m_menu->setFixedWidth(m_input->width());
}
break;
}
case QEvent::ParentChange:
qDebug() << "Parent change";
default:
break;
}
return QtMaterialOverlayWidget::eventFilter(obj, event);
}
void Xyz::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter painter(this);
QPen pen;
pen.setColor(Qt::red);
pen.setWidth(8);
painter.setPen(pen);
painter.drawRect(rect());
}
Menu::Menu(QWidget *parent)
: QWidget(parent)
{
QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect;
effect->setBlurRadius(11);
effect->setColor(QColor(0, 0, 0, 50));
effect->setOffset(0, 3);
setGraphicsEffect(effect);
setMinimumWidth(300);
QVBoxLayout *menuLayout = new QVBoxLayout;
menuLayout->setContentsMargins(0, 8, 0, 8);
setLayout(menuLayout);
QtMaterialFlatButton *fb1 = new QtMaterialFlatButton("Maps");
QtMaterialFlatButton *fb2 = new QtMaterialFlatButton("Books");
QtMaterialFlatButton *fb3 = new QtMaterialFlatButton("Flights");
QFont font("Roboto", 12, QFont::Normal);
//fb1->setIcon(QtMaterialTheme::icon("toggle", "star"));
fb1->setFont(font);
fb2->setFont(font);
fb3->setFont(font);
fb1->setTextAlignment(Qt::AlignLeft);
fb2->setTextAlignment(Qt::AlignLeft);
fb3->setTextAlignment(Qt::AlignLeft);
fb1->setMinimumHeight(50);
fb2->setMinimumHeight(50);
fb3->setMinimumHeight(50);
fb1->setHaloVisible(false);
fb2->setHaloVisible(false);
fb3->setHaloVisible(false);
menuLayout->addWidget(fb1);
menuLayout->addWidget(fb2);
menuLayout->addWidget(fb3);
menuLayout->setSpacing(0);
//setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
}
Menu::~Menu()
{
}
//QSize Menu::sizeHint() const
//{
// return QSize(300, 100);
//}
bool Menu::event(QEvent *event)
{
switch (event->type())
{
case QEvent::Move:
case QEvent::Resize:
break;
case QEvent::ParentChange:
default:
break;
}
return QWidget::event(event);
}
void Menu::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter painter(this);
//painter.fillRect(rect(), Qt::white);
//QPen pen;
//pen.setColor(Qt::blue);
//pen.setWidth(4);
//painter.setPen(pen);
//painter.drawRect(rect());
}

View File

@ -0,0 +1,63 @@
#ifndef AUTOCOMPLETESETTINGSEDITOR_H
#define AUTOCOMPLETESETTINGSEDITOR_H
#include <QWidget>
//#include "ui_autocompletesettingsform.h"
#include "lib/qtmaterialoverlaywidget.h"
class QtMaterialAutoComplete;
class AutoCompleteSettingsEditor : public QWidget
{
Q_OBJECT
public:
explicit AutoCompleteSettingsEditor(QWidget *parent = 0);
~AutoCompleteSettingsEditor();
protected slots:
void setupForm();
void updateWidget();
void selectColor();
private:
//Ui::AutoCompleteSettingsForm *const ui;
QtMaterialAutoComplete *const m_autocomplete;
};
class Menu;
class Xyz : public QtMaterialOverlayWidget
{
Q_OBJECT
public:
explicit Xyz(QtMaterialAutoComplete *input, QWidget *parent = 0);
~Xyz();
protected:
bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE;
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
private:
QtMaterialAutoComplete *const m_input;
Menu *const m_menu;
};
class Menu : public QWidget
{
Q_OBJECT
public:
Menu(QWidget *parent = 0);
~Menu();
//QSize sizeHint() const Q_DECL_OVERRIDE;
protected:
bool event(QEvent *event) Q_DECL_OVERRIDE;
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
};
#endif // AUTOCOMPLETESETTINGSEDITOR_H

View File

@ -21,7 +21,8 @@ SOURCES = mainwindow.cpp \
dialogsettingseditor.cpp \
drawersettingseditor.cpp \
scrollbarsettingseditor.cpp \
appbarsettingseditor.cpp
appbarsettingseditor.cpp \
autocompletesettingseditor.cpp
HEADERS = mainwindow.h \
avatarsettingseditor.h \
badgesettingseditor.h \
@ -41,7 +42,8 @@ HEADERS = mainwindow.h \
dialogsettingseditor.h \
drawersettingseditor.h \
scrollbarsettingseditor.h \
appbarsettingseditor.h
appbarsettingseditor.h \
autocompletesettingseditor.h
LIBS += $$top_builddir/components/$(OBJECTS_DIR)/libcomponents.a
INCLUDEPATH += $$top_srcdir/components/
TARGET = examples-exe

View File

@ -21,6 +21,7 @@
#include "drawersettingseditor.h"
#include "scrollbarsettingseditor.h"
#include "appbarsettingseditor.h"
#include "autocompletesettingseditor.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
@ -59,8 +60,10 @@ MainWindow::MainWindow(QWidget *parent)
DrawerSettingsEditor *drawer = new DrawerSettingsEditor;
ScrollBarSettingsEditor *scrollBar = new ScrollBarSettingsEditor;
AppBarSettingsEditor *appBar = new AppBarSettingsEditor;
AutoCompleteSettingsEditor *autocomplete = new AutoCompleteSettingsEditor;
stack->addWidget(appBar);
stack->addWidget(autocomplete);
stack->addWidget(avatar);
stack->addWidget(badge);
stack->addWidget(checkbox);
@ -81,6 +84,7 @@ MainWindow::MainWindow(QWidget *parent)
stack->addWidget(toggle);
list->addItem("App Bar");
list->addItem("Auto Complete");
list->addItem("Avatar");
list->addItem("Badge");
list->addItem("Checkbox");