Commit 8e51a93d authored by Eike Ziller's avatar Eike Ziller

Make find options in tool bar more accessible.

Open a popup that doesn't close on every change of an option.
Make the options button accessible through tab.

Task-number: QTCREATORBUG-11340

Change-Id: I61b83243ead4b0b3d7075c1e8f8327cd31d9c2c4
Reviewed-by: default avatarBojan Petrovic <bojan85@gmail.com>
Reviewed-by: Orgad Shaneh's avatarOrgad Shaneh <orgads@gmail.com>
parent 880a834b
......@@ -30,13 +30,14 @@
#include "execmenu.h"
#include "fancylineedit.h"
#include "historycompleter.h"
#include "hostosinfo.h"
#include "qtcassert.h"
#include <QAbstractItemView>
#include <QDebug>
#include <QKeyEvent>
#include <QMenu>
#include <QPainter>
#include <QStylePainter>
#include <QPropertyAnimation>
#include <QStyle>
......@@ -184,6 +185,11 @@ bool FancyLineEdit::isButtonVisible(Side side) const
return d->m_iconEnabled[side];
}
QAbstractButton *FancyLineEdit::button(FancyLineEdit::Side side) const
{
return d->m_iconbutton[side];
}
void FancyLineEdit::iconClicked()
{
IconButton *button = qobject_cast<IconButton *>(sender());
......@@ -480,7 +486,7 @@ IconButton::IconButton(QWidget *parent)
void IconButton::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QStylePainter painter(this);
QRect pixmapRect = QRect(0, 0, m_pixmap.width(), m_pixmap.height());
pixmapRect.moveCenter(rect().center());
......@@ -488,6 +494,18 @@ void IconButton::paintEvent(QPaintEvent *)
painter.setOpacity(m_iconOpacity);
painter.drawPixmap(pixmapRect, m_pixmap);
if (hasFocus()) {
QStyleOptionFocusRect focusOption;
focusOption.initFrom(this);
focusOption.rect = pixmapRect;
if (HostOsInfo::isMacHost()) {
focusOption.rect.adjust(-4, -4, 4, 4);
painter.drawControl(QStyle::CE_FocusFrame, focusOption);
} else {
painter.drawPrimitive(QStyle::PE_FrameFocusRect, focusOption);
}
}
}
void IconButton::animateShow(bool visible)
......@@ -505,4 +523,20 @@ void IconButton::animateShow(bool visible)
}
}
void IconButton::keyPressEvent(QKeyEvent *ke)
{
QAbstractButton::keyPressEvent(ke);
if (!ke->modifiers() && (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return))
click();
// do not forward to line edit
ke->accept();
}
void IconButton::keyReleaseEvent(QKeyEvent *ke)
{
QAbstractButton::keyReleaseEvent(ke);
// do not forward to line edit
ke->accept();
}
} // namespace Utils
......@@ -60,6 +60,11 @@ public:
void setAutoHide(bool hide) { m_autoHide = hide; }
bool hasAutoHide() const { return m_autoHide; }
protected:
void keyPressEvent(QKeyEvent *ke);
void keyReleaseEvent(QKeyEvent *ke);
private:
float m_iconOpacity;
bool m_autoHide;
......@@ -89,6 +94,7 @@ public:
void setButtonVisible(Side side, bool visible);
bool isButtonVisible(Side side) const;
QAbstractButton *button(Side side) const;
void setButtonToolTip(Side side, const QString &);
void setButtonFocusPolicy(Side side, Qt::FocusPolicy policy);
......
......@@ -42,10 +42,12 @@
#include <utils/hostosinfo.h>
#include <utils/flowlayout.h>
#include <utils/qtcassert.h>
#include <QDebug>
#include <QSettings>
#include <QCheckBox>
#include <QClipboard>
#include <QCompleter>
#include <QKeyEvent>
......@@ -100,14 +102,15 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen
m_ui.findEdit->setSpecialCompleter(m_findCompleter);
m_ui.replaceEdit->setSpecialCompleter(m_replaceCompleter);
QMenu *lineEditMenu = new QMenu(m_ui.findEdit);
m_ui.findEdit->setButtonMenu(Utils::FancyLineEdit::Left, lineEditMenu);
m_ui.findEdit->setButtonVisible(Utils::FancyLineEdit::Left, true);
m_ui.findEdit->setFiltering(true);
m_ui.findEdit->setPlaceholderText(QString());
m_ui.findEdit->button(Utils::FancyLineEdit::Left)->setFocusPolicy(Qt::TabFocus);
m_ui.replaceEdit->setPlaceholderText(QString());
connect(m_ui.findEdit, SIGNAL(textChanged(QString)), this, SLOT(invokeFindIncremental()));
connect(m_ui.findEdit, SIGNAL(leftButtonClicked()),
this, SLOT(findEditButtonClicked()));
// invoke{Find,Replace}Helper change the completion model. QueuedConnection is used to perform these
// changes only after the completer's activated() signal is handled (QTCREATORBUG-8408)
......@@ -222,8 +225,7 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen
m_caseSensitiveAction->setChecked(false);
cmd = Core::ActionManager::registerAction(m_caseSensitiveAction, Constants::CASE_SENSITIVE, globalcontext);
mfind->addAction(cmd, Constants::G_FIND_FLAGS);
connect(m_caseSensitiveAction, SIGNAL(triggered(bool)), this, SLOT(setCaseSensitive(bool)));
lineEditMenu->addAction(m_caseSensitiveAction);
connect(m_caseSensitiveAction, SIGNAL(toggled(bool)), this, SLOT(setCaseSensitive(bool)));
m_wholeWordAction = new QAction(tr("Whole Words Only"), this);
m_wholeWordAction->setIcon(QIcon(QLatin1String(":/find/images/wholewords.png")));
......@@ -231,8 +233,7 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen
m_wholeWordAction->setChecked(false);
cmd = Core::ActionManager::registerAction(m_wholeWordAction, Constants::WHOLE_WORDS, globalcontext);
mfind->addAction(cmd, Constants::G_FIND_FLAGS);
connect(m_wholeWordAction, SIGNAL(triggered(bool)), this, SLOT(setWholeWord(bool)));
lineEditMenu->addAction(m_wholeWordAction);
connect(m_wholeWordAction, SIGNAL(toggled(bool)), this, SLOT(setWholeWord(bool)));
m_regularExpressionAction = new QAction(tr("Use Regular Expressions"), this);
m_regularExpressionAction->setIcon(QIcon(QLatin1String(":/find/images/regexp.png")));
......@@ -240,8 +241,7 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen
m_regularExpressionAction->setChecked(false);
cmd = Core::ActionManager::registerAction(m_regularExpressionAction, Constants::REGULAR_EXPRESSIONS, globalcontext);
mfind->addAction(cmd, Constants::G_FIND_FLAGS);
connect(m_regularExpressionAction, SIGNAL(triggered(bool)), this, SLOT(setRegularExpressions(bool)));
lineEditMenu->addAction(m_regularExpressionAction);
connect(m_regularExpressionAction, SIGNAL(toggled(bool)), this, SLOT(setRegularExpressions(bool)));
m_preserveCaseAction = new QAction(tr("Preserve Case when Replacing"), this);
m_preserveCaseAction->setIcon(QPixmap(QLatin1String(":/find/images/preservecase.png")));
......@@ -249,8 +249,7 @@ FindToolBar::FindToolBar(FindPlugin *plugin, CurrentDocumentFind *currentDocumen
m_preserveCaseAction->setChecked(false);
cmd = Core::ActionManager::registerAction(m_preserveCaseAction, Constants::PRESERVE_CASE, globalcontext);
mfind->addAction(cmd, Constants::G_FIND_FLAGS);
connect(m_preserveCaseAction, SIGNAL(triggered(bool)), this, SLOT(setPreserveCase(bool)));
lineEditMenu->addAction(m_preserveCaseAction);
connect(m_preserveCaseAction, SIGNAL(toggled(bool)), this, SLOT(setPreserveCase(bool)));
connect(m_currentDocumentFind, SIGNAL(candidateChanged()), this, SLOT(adaptToCandidate()));
connect(m_currentDocumentFind, SIGNAL(changed()), this, SLOT(updateToolBar()));
......@@ -554,6 +553,12 @@ void FindToolBar::findFlagsChanged()
m_currentDocumentFind->highlightAll(getFindText(), effectiveFindFlags());
}
void FindToolBar::findEditButtonClicked()
{
OptionsPopup *popup = new OptionsPopup(m_ui.findEdit);
popup->show();
}
void FindToolBar::updateIcons()
{
FindFlags effectiveFlags = effectiveFindFlags();
......@@ -685,11 +690,16 @@ void FindToolBar::findPreviousSelected()
bool FindToolBar::focusNextPrevChild(bool next)
{
// close tab order change
QAbstractButton *optionsButton = m_ui.findEdit->button(Utils::FancyLineEdit::Left);
// close tab order
if (next && m_ui.advancedButton->hasFocus())
optionsButton->setFocus(Qt::TabFocusReason);
else if (next && optionsButton->hasFocus())
m_ui.findEdit->setFocus(Qt::TabFocusReason);
else if (!next && m_ui.findEdit->hasFocus())
else if (!next && optionsButton->hasFocus())
m_ui.advancedButton->setFocus(Qt::TabFocusReason);
else if (!next && m_ui.findEdit->hasFocus())
optionsButton->setFocus(Qt::TabFocusReason);
else
return Utils::StyledBar::focusNextPrevChild(next);
return true;
......@@ -778,3 +788,69 @@ void FindToolBar::setBackward(bool backward)
{
setFindFlag(FindBackward, backward);
}
OptionsPopup::OptionsPopup(QWidget *parent)
: QWidget(parent, Qt::Popup)
{
setAttribute(Qt::WA_DeleteOnClose);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setContentsMargins(2, 2, 2, 2);
layout->setSpacing(2);
setLayout(layout);
QCheckBox *firstCheckBox = createCheckboxForCommand(Constants::CASE_SENSITIVE);
layout->addWidget(firstCheckBox);
layout->addWidget(createCheckboxForCommand(Constants::WHOLE_WORDS));
layout->addWidget(createCheckboxForCommand(Constants::REGULAR_EXPRESSIONS));
layout->addWidget(createCheckboxForCommand(Constants::PRESERVE_CASE));
firstCheckBox->setFocus();
move(parent->mapToGlobal(QPoint(0, -sizeHint().height())));
}
bool OptionsPopup::event(QEvent *ev)
{
if (ev->type() == QEvent::ShortcutOverride) {
QKeyEvent *ke = static_cast<QKeyEvent *>(ev);
if (ke->key() == Qt::Key_Escape && !ke->modifiers()) {
ev->accept();
return true;
}
}
return QWidget::event(ev);
}
bool OptionsPopup::eventFilter(QObject *obj, QEvent *ev)
{
QCheckBox *checkbox = qobject_cast<QCheckBox *>(obj);
if (ev->type() == QEvent::KeyPress && checkbox) {
QKeyEvent *ke = static_cast<QKeyEvent *>(ev);
if (!ke->modifiers() && (ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Return)) {
checkbox->click();
ev->accept();
return true;
}
}
return QWidget::eventFilter(obj, ev);
}
void OptionsPopup::actionChanged()
{
QAction *action = qobject_cast<QAction *>(sender());
QTC_ASSERT(action, return);
QCheckBox *checkbox = m_checkboxMap.value(action);
QTC_ASSERT(checkbox, return);
checkbox->setEnabled(action->isEnabled());
}
QCheckBox *OptionsPopup::createCheckboxForCommand(Id id)
{
QAction *action = ActionManager::command(id)->action();
QCheckBox *checkbox = new QCheckBox(action->text());
checkbox->setToolTip(action->toolTip());
checkbox->setChecked(action->isChecked());
checkbox->setEnabled(action->isEnabled());
checkbox->installEventFilter(this); // enter key handling
QObject::connect(checkbox, SIGNAL(clicked(bool)), action, SLOT(setChecked(bool)));
QObject::connect(action, SIGNAL(changed()), this, SLOT(actionChanged()));
m_checkboxMap.insert(action, checkbox);
return checkbox;
}
......@@ -33,10 +33,15 @@
#include "ui_findwidget.h"
#include "currentdocumentfind.h"
#include <coreplugin/id.h>
#include <utils/styledbar.h>
#include <QTimer>
QT_BEGIN_NAMESPACE
class QCheckBox;
QT_END_NAMESPACE
namespace Core {
class FindToolBarPlaceHolder;
......@@ -44,6 +49,26 @@ class FindPlugin;
namespace Internal {
class OptionsPopup : public QWidget
{
Q_OBJECT
public:
explicit OptionsPopup(QWidget *parent);
protected:
bool event(QEvent *ev);
bool eventFilter(QObject *obj, QEvent *ev);
private slots:
void actionChanged();
private:
QCheckBox *createCheckboxForCommand(Id id);
QMap<QAction *, QCheckBox *> m_checkboxMap;
};
class FindToolBar : public Utils::StyledBar
{
Q_OBJECT
......@@ -85,6 +110,7 @@ private slots:
void updateFindAction();
void updateToolBar();
void findFlagsChanged();
void findEditButtonClicked();
void setCaseSensitive(bool sensitive);
void setWholeWord(bool wholeOnly);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment