diff --git a/src/DropDownListFrame.cpp b/src/DropDownListFrame.cpp index 16861d53..e6421d52 100644 --- a/src/DropDownListFrame.cpp +++ b/src/DropDownListFrame.cpp @@ -11,13 +11,19 @@ DropDownListFrame::DropDownListFrame(QWidget *parent) { qApp->installEventFilter(this); installEventFilter(this); - + setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint); auto *layout = new QVBoxLayout; layout->setContentsMargins(0, 0, 0, 0); setLayout(layout); listw_ = new QListWidget; layout->addWidget(listw_); + + connect(listw_, &QListWidget::itemClicked, [this](QListWidgetItem *item) { + QString s = item->text(); + emit itemClicked(item->text()); + emit done(); + }); } void DropDownListFrame::addItem(const QString &text) @@ -33,7 +39,7 @@ void DropDownListFrame::setItems(const QStringList &list) } } -void DropDownListFrame::show() +void DropDownListFrame::show_() { QWidget *par = parentWidget(); QPoint pt = par->geometry().bottomLeft(); @@ -43,31 +49,38 @@ void DropDownListFrame::show() listw_->setFixedHeight(height); setFixedHeight(height); setGeometry(pt.x(), pt.y(), par->geometry().width(), height); - QFrame::show(); + QFrame::setVisible(true); activateWindow(); listw_->setFocus(); listw_->setCurrentRow(0); } +void DropDownListFrame::setVisible(bool visible) +{ + if (visible) { + show_(); + } else { + QFrame::setVisible(false); + } +} + void DropDownListFrame::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: - hide(); + emit done(); return; case Qt::Key_Return: emit itemClicked(listw_->currentItem()->text()); - hide(); + emit done(); return; } QFrame::keyPressEvent(event); } - - void DropDownListFrame::focusOutEvent(QFocusEvent *event) { - hide(); + emit done(); event->accept(); } @@ -78,17 +91,30 @@ bool DropDownListFrame::eventFilter(QObject *watched, QEvent *event) if (isVisible()) { QKeyEvent *e = static_cast(event); if (e->key() == Qt::Key_Tab || e->key() == Qt::Key_Backtab) { - hide(); + emit done(); return true; } } break; case QEvent::WindowDeactivate: if (watched == this) { - hide(); + emit done(); return true; } break; + case QEvent::MouseButtonPress: + { + QWidget *w = qobject_cast(watched); + if (w) { + QPoint p = static_cast(event)->pos(); + p = w->mapToGlobal(p); + if (!geometry().contains(p)) { // clicked outside + emit done(); + return true; + } + } + } + break; } return QFrame::eventFilter(watched, event); } diff --git a/src/DropDownListFrame.h b/src/DropDownListFrame.h index 6af97f7c..db01c3a8 100644 --- a/src/DropDownListFrame.h +++ b/src/DropDownListFrame.h @@ -13,13 +13,16 @@ class DropDownListFrame : public QFrame { DropDownListFrame(QWidget *parent); void addItem(QString const &text); void setItems(QStringList const &list); - void show(); + void show_(); protected: bool eventFilter(QObject *watched, QEvent *event); void focusOutEvent(QFocusEvent *event); void keyPressEvent(QKeyEvent *event); +public slots: + void setVisible(bool visible); signals: void itemClicked(QString const &text); + void done(); }; #endif // DROPDOWNLISTFRAME_H diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 1c575f04..d21404a2 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -649,7 +649,7 @@ bool MainWindow::event(QEvent *event) return true; } } - } else if (et == (QEvent::Type)UserEvent::UserFunction) { + } else if (et == UserEvent(UserFunction)) { if (auto *e = (UserFunctionEvent *)event) { e->func(e->var, e->ptr); return true; @@ -660,7 +660,7 @@ bool MainWindow::event(QEvent *event) void MainWindow::customEvent(QEvent *e) { - if (e->type() == (QEvent::Type)UserEvent::Start) { + if (e->type() == UserEvent(Start)) { onStartEvent(); return; } diff --git a/src/RepositoryUrlLineEdit.cpp b/src/RepositoryUrlLineEdit.cpp index 26c9506b..3629a03f 100644 --- a/src/RepositoryUrlLineEdit.cpp +++ b/src/RepositoryUrlLineEdit.cpp @@ -8,37 +8,38 @@ #include #include -class CtrlSpaceEvent : public QEvent { +namespace { + +class MyEvent : public QEvent { public: - bool forward_ = true; - CtrlSpaceEvent(bool forward) + int key = 0; + MyEvent(int key) : QEvent(QEvent::User) - , forward_(forward) + , key(key) { } }; +} // namespace + struct RepositoryUrlLineEdit::Private { QStringList url_candidates; - DropDownListFrame *drop_down_frame = nullptr; - QRect drop_down_botton_rect; + DropDownListFrame *drop_down_list = nullptr; }; RepositoryUrlLineEdit::RepositoryUrlLineEdit(QWidget *parent) : QLineEdit{parent} , m{new Private} { - m->drop_down_frame = new DropDownListFrame(this); - installEventFilter(this); - - connect(m->drop_down_frame, &DropDownListFrame::itemClicked, [this](QString const &text) { - setText(text); - m->drop_down_frame->hide(); + + m->drop_down_list = new DropDownListFrame(this); + connect(m->drop_down_list, &DropDownListFrame::itemClicked, [this](const QString &item) { + setText(item); }); - - connect(this, &QLineEdit::textChanged, [this](const QString &text) { - setText(text); + connect(m->drop_down_list, &DropDownListFrame::done, [this]() { + m->drop_down_list->close(); + qApp->postEvent(this, new QFocusEvent(QEvent::FocusIn)); }); } @@ -142,78 +143,21 @@ void RepositoryUrlLineEdit::setNextRepositoryUrlCandidate(bool forward) } } -/** - * @brief RepositoryUrlLineEdit::showDropDown - * - * ドロップダウンリストを表示する - */ -void RepositoryUrlLineEdit::showDropDown() -{ - updateRepositoryUrlCandidates(); - m->drop_down_frame->setItems(m->url_candidates); - m->drop_down_frame->show(); -} - -void RepositoryUrlLineEdit::paintEvent(QPaintEvent *event) -{ - const int w = width(); - const int h = height(); - m->drop_down_botton_rect = QRect(w - h, 0, h, h); - - QLineEdit::paintEvent(event); - QPainter pr(this); - QStyleOption opt; - opt.initFrom(this); - opt.rect = m->drop_down_botton_rect; - qApp->style()->drawPrimitive(QStyle::PE_IndicatorButtonDropDown, &opt, &pr, this); -} - -void RepositoryUrlLineEdit::mouseMoveEvent(QMouseEvent *event) -{ - QPoint p = event->pos(); - if (m->drop_down_botton_rect.contains(p)) { - setCursor(Qt::ArrowCursor); - event->accept(); - return; - } - QLineEdit::mouseMoveEvent(event); -} - -void RepositoryUrlLineEdit::mousePressEvent(QMouseEvent *event) -{ - QPoint p = event->pos(); - if (m->drop_down_botton_rect.contains(p)) { - showDropDown(); - event->accept(); - return; - } - QLineEdit::mousePressEvent(event); -} - -void RepositoryUrlLineEdit::mouseDoubleClickEvent(QMouseEvent *event) -{ - QPoint p = event->pos(); - if (m->drop_down_botton_rect.contains(p)) { - showDropDown(); - event->accept(); - return; - } - QLineEdit::mouseDoubleClickEvent(event); -} - -void RepositoryUrlLineEdit::keyPressEvent(QKeyEvent *event) -{ - if (event->key() == Qt::Key_Down) { - showDropDown(); - } - QLineEdit::keyPressEvent(event); -} - void RepositoryUrlLineEdit::customEvent(QEvent *event) { if (event->type() == QEvent::User) { - CtrlSpaceEvent *e = static_cast(event); - setNextRepositoryUrlCandidate(e->forward_); + MyEvent *e = static_cast(event); + if (e->key == Qt::Key_Space) { + setNextRepositoryUrlCandidate(true); + return; + } + if (e->key == Qt::Key_Down) { + updateRepositoryUrlCandidates(); + m->drop_down_list->setItems(m->url_candidates); + m->drop_down_list->show(); + return; + } + return; } } @@ -222,8 +166,11 @@ bool RepositoryUrlLineEdit::eventFilter(QObject *watched, QEvent *event) if (event->type() == QEvent::KeyPress) { QKeyEvent *e = static_cast(event); if (e->key() == Qt::Key_Space && (e->modifiers() & Qt::ControlModifier)) { - bool forward = !(e->modifiers() & Qt::ShiftModifier); - QApplication::postEvent(this, new CtrlSpaceEvent(forward)); + QApplication::postEvent(this, new MyEvent(e->key())); + return true; + } + if (e->key() == Qt::Key_Down) { + QApplication::postEvent(this, new MyEvent(e->key())); return true; } } diff --git a/src/RepositoryUrlLineEdit.h b/src/RepositoryUrlLineEdit.h index 972bcd03..75a3cf1d 100644 --- a/src/RepositoryUrlLineEdit.h +++ b/src/RepositoryUrlLineEdit.h @@ -12,13 +12,7 @@ class RepositoryUrlLineEdit : public QLineEdit { struct Private; Private *m; void updateRepositoryUrlCandidates(); - void showDropDown(); protected: - void keyPressEvent(QKeyEvent *event); - void mouseDoubleClickEvent(QMouseEvent *event); - void mouseMoveEvent(QMouseEvent *event); - void mousePressEvent(QMouseEvent *event); - void paintEvent(QPaintEvent *event); void customEvent(QEvent *event); bool eventFilter(QObject *watched, QEvent *event); public: diff --git a/src/UserEvent.h b/src/UserEvent.h index b753b9ca..959794c0 100644 --- a/src/UserEvent.h +++ b/src/UserEvent.h @@ -5,15 +5,16 @@ #include #include -enum class UserEvent { +enum class UserEventEnum { Start = QEvent::User, UserFunction, }; +#define UserEvent(e) QEvent::Type(UserEventEnum::e) class StartEvent : public QEvent { public: StartEvent() - : QEvent((QEvent::Type)UserEvent::Start) + : QEvent(UserEvent(Start)) { } }; @@ -25,7 +26,7 @@ class UserFunctionEvent : public QEvent { void *ptr = nullptr; explicit UserFunctionEvent(std::function func, QVariant const &var, void *ptr = nullptr) - : QEvent((QEvent::Type)UserEvent::UserFunction) + : QEvent(UserEvent(UserFunction)) , func(func) , var(var) , ptr(ptr)