X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fautocomplete.cpp;h=8ef4d317d7e910766abbd7b07edfc6ce12864896;hb=77808d40003c9f0182d8ae59f05c1c2e59e9c4c1;hp=e6e0d429af0fd4e9d08966c35a465d8371439154;hpb=5dda8b7361aba8cc892b09125d69daed8e13ec50;p=minitube diff --git a/src/autocomplete.cpp b/src/autocomplete.cpp index e6e0d42..8ef4d31 100644 --- a/src/autocomplete.cpp +++ b/src/autocomplete.cpp @@ -19,51 +19,76 @@ along with Minitube. If not, see . $END_LICENSE */ #include "autocomplete.h" #include "suggester.h" -#ifdef APP_MAC +#ifdef APP_MAC_SEARCHFIELD #include "searchlineedit_mac.h" #else #include "searchlineedit.h" #endif -AutoComplete::AutoComplete(SearchLineEdit *buddy, QLineEdit *lineEdit): - QObject(buddy), buddy(buddy), lineEdit(lineEdit), suggester(0) { +#ifdef APP_MAC +#include "macutils.h" +#endif - enabled = true; +#include + +#ifndef QT_NO_DEBUG_OUTPUT +/// Gives human-readable event type information. +QDebug operator<<(QDebug str, const QEvent * ev) { + static int eventEnumIndex = QEvent::staticMetaObject.indexOfEnumerator("Type"); + str << "QEvent"; + if (ev) { + QString name = QEvent::staticMetaObject.enumerator(eventEnumIndex).valueToKey(ev->type()); + if (!name.isEmpty()) str << name; else str << ev->type(); + } else { + str << (void*)ev; + } + return str.maybeSpace(); +} +#endif + +AutoComplete::AutoComplete(SearchWidget *buddy, QLineEdit *lineEdit): + QObject(lineEdit), buddy(buddy), lineEdit(lineEdit), enabled(true), suggester(0), itemHovering(false) { popup = new QListWidget(); - popup->setMouseTracking(true); popup->setWindowFlags(Qt::Popup); - popup->setAttribute(Qt::WA_ShowWithoutActivating); - popup->setFocusPolicy(Qt::NoFocus); - popup->setFocusProxy(buddy); + popup->setFocusProxy(buddy->toWidget()); popup->installEventFilter(this); + buddy->toWidget()->window()->installEventFilter(this); + popup->setMouseTracking(true); + // style popup->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); popup->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); popup->setWindowOpacity(.9); popup->setProperty("suggest", true); - popup->setFrameShape(QFrame::NoFrame); - popup->setAttribute(Qt::WA_TranslucentBackground); - popup->viewport()->setStyleSheet("border:0; border-radius:5px; background:palette(base)"); connect(popup, SIGNAL(itemClicked(QListWidgetItem*)), SLOT(acceptSuggestion())); connect(popup, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), - SLOT(currentItemChanged(QListWidgetItem*))); + SLOT(currentItemChanged(QListWidgetItem*))); connect(popup, SIGNAL(itemEntered(QListWidgetItem*)), SLOT(itemEntered(QListWidgetItem *))); timer = new QTimer(this); timer->setSingleShot(true); timer->setInterval(500); connect(timer, SIGNAL(timeout()), SLOT(suggest())); - connect(buddy, SIGNAL(textEdited(QString)), timer, SLOT(start())); -} - -AutoComplete::~AutoComplete() { - delete popup; + connect(buddy->toWidget(), SIGNAL(textEdited(QString)), timer, SLOT(start())); } bool AutoComplete::eventFilter(QObject *obj, QEvent *ev) { - if (obj != popup) return false; + + if (obj != popup) { + switch (ev->type()) { + case QEvent::Move: + case QEvent::Resize: + adjustPosition(); + break; + default: + break; + } + return false; + } + + // qDebug() << ev; if (ev->type() == QEvent::Leave) { popup->setCurrentItem(0); @@ -72,10 +97,8 @@ bool AutoComplete::eventFilter(QObject *obj, QEvent *ev) { return true; } - if (ev->type() == QEvent::FocusOut) { - popup->hide(); - buddy->setText(originalText); - buddy->setFocus(); + if (ev->type() == QEvent::FocusOut || ev->type() == QEvent::MouseButtonPress) { + hideSuggestions(); return true; } @@ -90,17 +113,13 @@ bool AutoComplete::eventFilter(QObject *obj, QEvent *ev) { acceptSuggestion(); consumed = true; } else { - buddy->setFocus(); lineEdit->event(ev); - popup->hide(); + hideSuggestions(); } break; case Qt::Key_Escape: - popup->hide(); - popup->clear(); - buddy->setText(originalText); - buddy->setFocus(); + hideSuggestions(); consumed = true; break; @@ -109,7 +128,7 @@ bool AutoComplete::eventFilter(QObject *obj, QEvent *ev) { popup->setCurrentItem(0); popup->clearSelection(); buddy->setText(originalText); - buddy->setFocus(); + buddy->toWidget()->setFocus(); consumed = true; } break; @@ -135,46 +154,45 @@ bool AutoComplete::eventFilter(QObject *obj, QEvent *ev) { return false; } -void AutoComplete::showCompletion(const QList &suggestions) { +void AutoComplete::showSuggestions(const QList &suggestions) { if (suggestions.isEmpty()) { - popup->clear(); - popup->hide(); + hideSuggestions(); return; } popup->setUpdatesEnabled(false); popup->clear(); for (int i = 0; i < suggestions.count(); ++i) { - QListWidgetItem * item; - item = new QListWidgetItem(popup); + QListWidgetItem *item = new QListWidgetItem(popup); Suggestion *s = suggestions[i]; item->setText(s->value); if (!s->type.isEmpty()) item->setIcon(QIcon(":/images/" + s->type + ".png")); } popup->setCurrentItem(0); - int h = 0; + int h = popup->frameWidth() * 2; for (int i = 0; i < suggestions.count(); ++i) h += popup->sizeHintForRow(i); - popup->resize(buddy->width(), h); - popup->move(buddy->mapToGlobal(QPoint(0, buddy->height()))); - popup->setFocus(); - if (popup->isHidden()) popup->show(); + popup->resize(buddy->toWidget()->width(), h); + adjustPosition(); popup->setUpdatesEnabled(true); + + if (popup->isHidden()) { + itemHovering = false; + popup->showNormal(); + QTimer::singleShot(100, this, SLOT(enableItemHovering())); + } } void AutoComplete::acceptSuggestion() { - timer->stop(); - originalText.clear(); - popup->hide(); - buddy->setFocus(); int index = popup->currentIndex().row(); if (index >= 0 && index < suggestions.size()) { Suggestion* suggestion = suggestions.at(index); buddy->setText(suggestion->value); emit suggestionAccepted(suggestion); emit suggestionAccepted(suggestion->value); - popup->clear(); + originalText.clear(); + hideSuggestions(); } else qWarning() << "No suggestion for index" << index; } @@ -182,7 +200,6 @@ void AutoComplete::preventSuggest() { timer->stop(); enabled = false; popup->hide(); - popup->setFrameShape(QFrame::NoFrame); } void AutoComplete::enableSuggest() { @@ -197,15 +214,13 @@ void AutoComplete::setSuggester(Suggester* suggester) { void AutoComplete::suggest() { if (!enabled) return; - if (!buddy->hasFocus()) return; popup->setCurrentItem(0); popup->clearSelection(); originalText = buddy->text(); if (originalText.isEmpty()) { - popup->hide(); - buddy->setFocus(); + hideSuggestions(); return; } @@ -216,11 +231,36 @@ void AutoComplete::suggestionsReady(const QList &suggestions) { qDeleteAll(this->suggestions); this->suggestions = suggestions; if (!enabled) return; - if (!buddy->hasFocus()) return; - showCompletion(suggestions); + if (!buddy->toWidget()->hasFocus() && buddy->toWidget()->isVisible()) return; + showSuggestions(suggestions); +} + +void AutoComplete::adjustPosition() { + popup->move(buddy->toWidget()->mapToGlobal(QPoint(0, buddy->toWidget()->height()))); +} + +void AutoComplete::enableItemHovering() { + itemHovering = true; +} + +void AutoComplete::hideSuggestions() { + itemHovering = false; +#ifdef APP_MAC_NO + mac::fadeOutWindow(popup); +#else + popup->hide(); + popup->clear(); +#endif + if (!originalText.isEmpty()) { + buddy->setText(originalText); + originalText.clear(); + } + buddy->toWidget()->setFocus(); + timer->stop(); } void AutoComplete::itemEntered(QListWidgetItem *item) { + if (!itemHovering) return; if (!item) return; item->setSelected(true); popup->setCurrentItem(item); @@ -229,5 +269,5 @@ void AutoComplete::itemEntered(QListWidgetItem *item) { void AutoComplete::currentItemChanged(QListWidgetItem *item) { if (!item) return; buddy->setText(item->text()); - // lineEdit->setSelection(originalText.length(), editor->text().length()); + // lineEdit->setSelection(originalText.length(), lineEdit->text().length()); }