forked from qt-creator/qt-creator
Add Locator to extra editor windows
And open a popup if other windows are active. That way we avoid switching to the main window. Change-Id: Ia6d8d3fb4361ac31e406356d40056a2c0b79d114 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -28,9 +28,14 @@
|
||||
#include "editorarea.h"
|
||||
#include "editormanager_p.h"
|
||||
|
||||
#include <aggregation/aggregate.h>
|
||||
#include <coreplugin/icontext.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <coreplugin/locator/locator.h>
|
||||
#include <coreplugin/locator/locatorwidget.h>
|
||||
#include <coreplugin/statusbarmanager.h>
|
||||
|
||||
#include <QStatusBar>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace Core {
|
||||
@@ -46,6 +51,14 @@ EditorWindow::EditorWindow(QWidget *parent) :
|
||||
setLayout(layout);
|
||||
layout->addWidget(m_area);
|
||||
setFocusProxy(m_area);
|
||||
auto statusBar = new QStatusBar;
|
||||
layout->addWidget(statusBar);
|
||||
auto splitter = new NonResizingSplitter(statusBar);
|
||||
splitter->setChildrenCollapsible(false);
|
||||
statusBar->addPermanentWidget(splitter, 10);
|
||||
auto locatorWidget = createStaticLocatorWidget(Locator::instance());
|
||||
splitter->addWidget(locatorWidget);
|
||||
splitter->addWidget(new QWidget);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
setAttribute(Qt::WA_QuitOnClose, false); // don't prevent Qt Creator from closing
|
||||
resize(QSize(800, 600));
|
||||
@@ -61,6 +74,11 @@ EditorWindow::EditorWindow(QWidget *parent) :
|
||||
deleteLater();
|
||||
});
|
||||
updateWindowTitle();
|
||||
|
||||
// register locator widget for this window
|
||||
auto agg = new Aggregation::Aggregate;
|
||||
agg->add(this);
|
||||
agg->add(locatorWidget);
|
||||
}
|
||||
|
||||
EditorWindow::~EditorWindow()
|
||||
|
@@ -86,6 +86,11 @@ Locator::~Locator()
|
||||
qDeleteAll(m_customFilters);
|
||||
}
|
||||
|
||||
Locator *Locator::instance()
|
||||
{
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
void Locator::initialize(CorePlugin *corePlugin, const QStringList &, QString *)
|
||||
{
|
||||
m_corePlugin = corePlugin;
|
||||
@@ -103,15 +108,14 @@ void Locator::initialize(CorePlugin *corePlugin, const QStringList &, QString *)
|
||||
ActionContainer *mtools = ActionManager::actionContainer(Constants::M_TOOLS);
|
||||
mtools->addAction(cmd);
|
||||
|
||||
auto locatorWidget = new LocatorWidget(this);
|
||||
new LocatorPopup(locatorWidget, locatorWidget); // child of locatorWidget
|
||||
m_locatorWidget = createStaticLocatorWidget(this);
|
||||
StatusBarWidget *view = new StatusBarWidget;
|
||||
view->setWidget(locatorWidget);
|
||||
view->setWidget(m_locatorWidget);
|
||||
view->setContext(Context("LocatorWidget"));
|
||||
view->setPosition(StatusBarWidget::First);
|
||||
m_corePlugin->addAutoReleasedObject(view);
|
||||
|
||||
new LocatorManager(locatorWidget);
|
||||
new LocatorManager(this);
|
||||
|
||||
m_openDocumentsFilter = new OpenDocumentsFilter;
|
||||
m_corePlugin->addObject(m_openDocumentsFilter);
|
||||
@@ -135,6 +139,11 @@ void Locator::initialize(CorePlugin *corePlugin, const QStringList &, QString *)
|
||||
|
||||
void Locator::extensionsInitialized()
|
||||
{
|
||||
// register locator widget for main window
|
||||
auto agg = new Aggregation::Aggregate;
|
||||
agg->add(ICore::mainWindow());
|
||||
agg->add(m_locatorWidget);
|
||||
|
||||
m_filters = ExtensionSystem::PluginManager::getObjects<ILocatorFilter>();
|
||||
Utils::sort(m_filters, [](const ILocatorFilter *first, const ILocatorFilter *second) -> bool {
|
||||
if (first->priority() != second->priority())
|
||||
@@ -341,6 +350,11 @@ void Locator::setRefreshInterval(int interval)
|
||||
m_refreshTimer.start();
|
||||
}
|
||||
|
||||
LocatorWidget *Locator::mainLocatorWidget()
|
||||
{
|
||||
return m_instance->m_locatorWidget;
|
||||
}
|
||||
|
||||
void Locator::refresh(QList<ILocatorFilter *> filters)
|
||||
{
|
||||
if (filters.isEmpty())
|
||||
|
@@ -43,6 +43,7 @@ class CorePlugin;
|
||||
class OpenDocumentsFilter;
|
||||
class FileSystemFilter;
|
||||
class LocatorSettingsPage;
|
||||
class LocatorWidget;
|
||||
class ExternalToolsFilter;
|
||||
|
||||
class Locator : public QObject
|
||||
@@ -53,6 +54,8 @@ public:
|
||||
Locator();
|
||||
~Locator();
|
||||
|
||||
static Locator *instance();
|
||||
|
||||
void initialize(CorePlugin *corePlugin, const QStringList &arguments, QString *errorMessage);
|
||||
void extensionsInitialized();
|
||||
bool delayedInitialize();
|
||||
@@ -63,6 +66,7 @@ public:
|
||||
void setCustomFilters(QList<ILocatorFilter *> f);
|
||||
int refreshInterval();
|
||||
void setRefreshInterval(int interval);
|
||||
static LocatorWidget *mainLocatorWidget();
|
||||
|
||||
signals:
|
||||
void filtersChanged();
|
||||
@@ -89,6 +93,7 @@ private:
|
||||
ExecuteFilter *m_executeFilter;
|
||||
CorePlugin *m_corePlugin = nullptr;
|
||||
ExternalToolsFilter *m_externalToolsFilter;
|
||||
LocatorWidget *m_locatorWidget;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
@@ -29,29 +29,45 @@
|
||||
#include "locator.h"
|
||||
#include "locatorwidget.h"
|
||||
|
||||
#include <aggregation/aggregate.h>
|
||||
#include <coreplugin/icore.h>
|
||||
#include <extensionsystem/pluginmanager.h>
|
||||
#include <utils/qtcassert.h>
|
||||
|
||||
using namespace Core::Internal;
|
||||
|
||||
namespace Core {
|
||||
|
||||
static Internal::LocatorWidget *m_locatorWidget = 0;
|
||||
|
||||
LocatorManager::LocatorManager(Internal::LocatorWidget *locatorWidget)
|
||||
: QObject(locatorWidget)
|
||||
LocatorManager::LocatorManager(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
m_locatorWidget = locatorWidget;
|
||||
}
|
||||
|
||||
static LocatorWidget *locatorWidget()
|
||||
{
|
||||
static QPointer<LocatorPopup> popup;
|
||||
QWidget *window = ICore::dialogParent()->window();
|
||||
if (auto *widget = Aggregation::query<LocatorWidget>(window)) {
|
||||
if (popup)
|
||||
popup->close();
|
||||
return widget;
|
||||
}
|
||||
if (!popup) {
|
||||
popup = createLocatorPopup(Locator::instance(), window);
|
||||
popup->show();
|
||||
}
|
||||
return popup->inputWidget();
|
||||
}
|
||||
|
||||
void LocatorManager::showFilter(ILocatorFilter *filter)
|
||||
{
|
||||
QTC_ASSERT(filter, return);
|
||||
QTC_ASSERT(m_locatorWidget, return);
|
||||
QString searchText = tr("<type here>");
|
||||
const QString currentText = m_locatorWidget->currentText().trimmed();
|
||||
const QString currentText = locatorWidget()->currentText().trimmed();
|
||||
// add shortcut string at front or replace existing shortcut string
|
||||
if (!currentText.isEmpty()) {
|
||||
searchText = currentText;
|
||||
foreach (ILocatorFilter *otherfilter, Internal::Locator::filters()) {
|
||||
foreach (ILocatorFilter *otherfilter, Locator::filters()) {
|
||||
if (currentText.startsWith(otherfilter->shortcutString() + QLatin1Char(' '))) {
|
||||
searchText = currentText.mid(otherfilter->shortcutString().length() + 1);
|
||||
break;
|
||||
@@ -66,8 +82,7 @@ void LocatorManager::showFilter(ILocatorFilter *filter)
|
||||
void LocatorManager::show(const QString &text,
|
||||
int selectionStart, int selectionLength)
|
||||
{
|
||||
QTC_ASSERT(m_locatorWidget, return);
|
||||
m_locatorWidget->showText(text, selectionStart, selectionLength);
|
||||
locatorWidget()->showText(text, selectionStart, selectionLength);
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Core
|
||||
|
@@ -40,7 +40,7 @@ class CORE_EXPORT LocatorManager : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LocatorManager(Internal::LocatorWidget *locatorWidget);
|
||||
LocatorManager(QObject *parent = 0);
|
||||
|
||||
static void showFilter(ILocatorFilter *filter);
|
||||
static void show(const QString &text, int selectionStart = -1, int selectionLength = 0);
|
||||
|
@@ -49,7 +49,9 @@
|
||||
#include <utils/stylehelper.h>
|
||||
#include <utils/utilsicons.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QColor>
|
||||
#include <QDesktopWidget>
|
||||
#include <QFileInfo>
|
||||
#include <QTimer>
|
||||
#include <QEvent>
|
||||
@@ -112,6 +114,28 @@ public:
|
||||
void showCurrentItemToolTip();
|
||||
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
bool eventFilter(QObject *watched, QEvent *event);
|
||||
};
|
||||
|
||||
class TopLeftLocatorPopup : public LocatorPopup
|
||||
{
|
||||
public:
|
||||
TopLeftLocatorPopup(LocatorWidget *locatorWidget)
|
||||
: LocatorPopup(locatorWidget, locatorWidget) {}
|
||||
|
||||
protected:
|
||||
void updateGeometry() override;
|
||||
void inputLostFocus() override;
|
||||
};
|
||||
|
||||
class CenteredLocatorPopup : public LocatorPopup
|
||||
{
|
||||
public:
|
||||
CenteredLocatorPopup(LocatorWidget *locatorWidget, QWidget *parent)
|
||||
: LocatorPopup(locatorWidget, parent) {}
|
||||
|
||||
protected:
|
||||
void updateGeometry() override;
|
||||
};
|
||||
|
||||
// =========== LocatorModel ===========
|
||||
@@ -226,6 +250,8 @@ CompletionList::CompletionList(QWidget *parent)
|
||||
const QStyleOptionViewItem &option = viewOptions();
|
||||
const QSize shint = itemDelegate()->sizeHint(option, QModelIndex());
|
||||
setFixedHeight(shint.height() * 17 + frameWidth() * 2);
|
||||
|
||||
installEventFilter(this);
|
||||
}
|
||||
|
||||
void CompletionList::setModel(QAbstractItemModel *newModel)
|
||||
@@ -241,20 +267,41 @@ void CompletionList::setModel(QAbstractItemModel *newModel)
|
||||
}
|
||||
}
|
||||
|
||||
void LocatorPopup::resize()
|
||||
void LocatorPopup::updateGeometry()
|
||||
{
|
||||
static const int MIN_WIDTH = 730;
|
||||
const QSize windowSize = m_window ? m_window->size() : QSize(MIN_WIDTH, 0);
|
||||
|
||||
const int width = qMax(MIN_WIDTH, windowSize.width() * 2 / 3);
|
||||
m_preferredSize = QSize(width, sizeHint().height());
|
||||
QWidget::resize(m_preferredSize);
|
||||
m_tree->resizeHeaders();
|
||||
}
|
||||
|
||||
QSize LocatorPopup::preferredSize() const
|
||||
void TopLeftLocatorPopup::updateGeometry()
|
||||
{
|
||||
return m_preferredSize;
|
||||
QTC_ASSERT(parentWidget(), return);
|
||||
const QSize size = preferredSize();
|
||||
const QRect rect(parentWidget()->mapToGlobal(QPoint(0, -size.height())), size);
|
||||
setGeometry(rect);
|
||||
LocatorPopup::updateGeometry();
|
||||
}
|
||||
|
||||
void CenteredLocatorPopup::updateGeometry()
|
||||
{
|
||||
QTC_ASSERT(parentWidget(), return);
|
||||
const QSize size = preferredSize();
|
||||
const QSize parentSize = parentWidget()->size();
|
||||
const QPoint pos = parentWidget()->mapToGlobal({(parentSize.width() - size.width()) / 2,
|
||||
parentSize.height() / 2 - size.height()});
|
||||
QRect rect(pos, size);
|
||||
// invisible widget doesn't have the right screen set yet, so use the parent widget to
|
||||
// check for available geometry
|
||||
const QRect available = QApplication::desktop()->availableGeometry(parentWidget());
|
||||
if (rect.right() > available.right())
|
||||
rect.moveRight(available.right());
|
||||
if (rect.bottom() > available.bottom())
|
||||
rect.moveBottom(available.bottom());
|
||||
if (rect.top() < available.top())
|
||||
rect.moveTop(available.top());
|
||||
if (rect.left() < available.left())
|
||||
rect.moveLeft(available.left());
|
||||
setGeometry(rect);
|
||||
LocatorPopup::updateGeometry();
|
||||
}
|
||||
|
||||
void LocatorPopup::updateWindow()
|
||||
@@ -271,25 +318,36 @@ void LocatorPopup::updateWindow()
|
||||
|
||||
bool LocatorPopup::event(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::ParentChange)
|
||||
if (event->type() == QEvent::ParentChange) {
|
||||
updateWindow();
|
||||
} else if (event->type() == QEvent::Show)
|
||||
updateGeometry();
|
||||
return QWidget::event(event);
|
||||
}
|
||||
|
||||
bool LocatorPopup::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
if (watched == m_window && event->type() == QEvent::Resize)
|
||||
resize();
|
||||
updateGeometry();
|
||||
return QWidget::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
void LocatorPopup::showPopup()
|
||||
QSize LocatorPopup::preferredSize()
|
||||
{
|
||||
static const int MIN_WIDTH = 730;
|
||||
const QSize windowSize = m_window ? m_window->size() : QSize(MIN_WIDTH, 0);
|
||||
|
||||
const int width = qMax(MIN_WIDTH, windowSize.width() * 2 / 3);
|
||||
return QSize(width, sizeHint().height());
|
||||
}
|
||||
|
||||
void TopLeftLocatorPopup::inputLostFocus()
|
||||
{
|
||||
hide();
|
||||
}
|
||||
|
||||
void LocatorPopup::inputLostFocus()
|
||||
{
|
||||
QTC_ASSERT(parentWidget(), return);
|
||||
const QSize size = preferredSize();
|
||||
const QRect rect(parentWidget()->mapToGlobal(QPoint(0, -size.height())), size);
|
||||
setGeometry(rect);
|
||||
show();
|
||||
}
|
||||
|
||||
void CompletionList::resizeHeaders()
|
||||
@@ -300,10 +358,9 @@ void CompletionList::resizeHeaders()
|
||||
|
||||
LocatorPopup::LocatorPopup(LocatorWidget *locatorWidget, QWidget *parent)
|
||||
: QWidget(parent),
|
||||
m_tree(new CompletionList(this))
|
||||
m_tree(new CompletionList(this)),
|
||||
m_inputWidget(locatorWidget)
|
||||
{
|
||||
setWindowFlags(Qt::ToolTip);
|
||||
|
||||
m_tree->setFrameStyle(QFrame::NoFrame);
|
||||
m_tree->setModel(locatorWidget->model());
|
||||
|
||||
@@ -315,8 +372,9 @@ LocatorPopup::LocatorPopup(LocatorWidget *locatorWidget, QWidget *parent)
|
||||
layout->addWidget(m_tree);
|
||||
|
||||
connect(locatorWidget, &LocatorWidget::parentChanged, this, &LocatorPopup::updateWindow);
|
||||
connect(locatorWidget, &LocatorWidget::showPopup, this, &LocatorPopup::showPopup);
|
||||
connect(locatorWidget, &LocatorWidget::hidePopup, this, &LocatorPopup::hide);
|
||||
connect(locatorWidget, &LocatorWidget::showPopup, this, &LocatorPopup::show);
|
||||
connect(locatorWidget, &LocatorWidget::hidePopup, this, &LocatorPopup::close);
|
||||
connect(locatorWidget, &LocatorWidget::lostFocus, this, &LocatorPopup::inputLostFocus);
|
||||
connect(locatorWidget, &LocatorWidget::selectRow, m_tree, [this](int row) {
|
||||
m_tree->setCurrentIndex(m_tree->model()->index(row, 0));
|
||||
});
|
||||
@@ -331,7 +389,7 @@ LocatorPopup::LocatorPopup(LocatorWidget *locatorWidget, QWidget *parent)
|
||||
locatorWidget->scheduleAcceptEntry(index);
|
||||
});
|
||||
|
||||
resize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
CompletionList *LocatorPopup::completionList() const
|
||||
@@ -339,6 +397,11 @@ CompletionList *LocatorPopup::completionList() const
|
||||
return m_tree;
|
||||
}
|
||||
|
||||
LocatorWidget *LocatorPopup::inputWidget() const
|
||||
{
|
||||
return m_inputWidget;
|
||||
}
|
||||
|
||||
void LocatorPopup::focusOutEvent(QFocusEvent *event) {
|
||||
if (event->reason() == Qt::ActiveWindowFocusReason)
|
||||
hide();
|
||||
@@ -402,6 +465,22 @@ void CompletionList::keyPressEvent(QKeyEvent *event)
|
||||
Utils::TreeView::keyPressEvent(event);
|
||||
}
|
||||
|
||||
bool CompletionList::eventFilter(QObject *watched, QEvent *event)
|
||||
{
|
||||
if (watched == this && event->type() == QEvent::ShortcutOverride) {
|
||||
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
|
||||
switch (ke->key()) {
|
||||
case Qt::Key_Escape:
|
||||
if (!ke->modifiers()) {
|
||||
event->accept();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Utils::TreeView::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
// =========== LocatorWidget ===========
|
||||
|
||||
LocatorWidget::LocatorWidget(Locator *locator) :
|
||||
@@ -576,7 +655,7 @@ bool LocatorWidget::eventFilter(QObject *obj, QEvent *event)
|
||||
}
|
||||
}
|
||||
} else if (obj == m_fileLineEdit && event->type() == QEvent::FocusOut) {
|
||||
emit hidePopup();
|
||||
emit lostFocus();
|
||||
} else if (obj == m_fileLineEdit && event->type() == QEvent::FocusIn) {
|
||||
QFocusEvent *fev = static_cast<QFocusEvent *>(event);
|
||||
if (fev->reason() != Qt::ActiveWindowFocusReason)
|
||||
@@ -796,5 +875,23 @@ void LocatorWidget::addSearchResults(int firstIndex, int endIndex)
|
||||
}
|
||||
}
|
||||
|
||||
LocatorWidget *createStaticLocatorWidget(Locator *locator)
|
||||
{
|
||||
auto widget = new LocatorWidget(locator);
|
||||
auto popup = new TopLeftLocatorPopup(widget); // owned by widget
|
||||
popup->setWindowFlags(Qt::ToolTip);
|
||||
return widget;
|
||||
}
|
||||
|
||||
LocatorPopup *createLocatorPopup(Locator *locator, QWidget *parent)
|
||||
{
|
||||
auto widget = new LocatorWidget(locator);
|
||||
auto popup = new CenteredLocatorPopup(widget, parent);
|
||||
popup->layout()->addWidget(widget);
|
||||
popup->setWindowFlags(Qt::Popup);
|
||||
popup->setAttribute(Qt::WA_DeleteOnClose);
|
||||
return popup;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Core
|
||||
|
@@ -64,6 +64,7 @@ public:
|
||||
|
||||
signals:
|
||||
void showCurrentItemToolTip();
|
||||
void lostFocus();
|
||||
void hidePopup();
|
||||
void selectRow(int row);
|
||||
void handleKey(QKeyEvent *keyEvent); // only use with DirectConnection, event is deleted
|
||||
@@ -109,21 +110,28 @@ public:
|
||||
LocatorPopup(LocatorWidget *locatorWidget, QWidget *parent = 0);
|
||||
|
||||
CompletionList *completionList() const;
|
||||
LocatorWidget *inputWidget() const;
|
||||
|
||||
void focusOutEvent (QFocusEvent *event) override;
|
||||
void resize();
|
||||
QSize preferredSize() const;
|
||||
bool event(QEvent *event) override;
|
||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
|
||||
protected:
|
||||
QSize preferredSize();
|
||||
virtual void updateGeometry();
|
||||
virtual void inputLostFocus();
|
||||
|
||||
QPointer<QWidget> m_window;
|
||||
|
||||
private:
|
||||
void showPopup();
|
||||
void updateWindow();
|
||||
|
||||
CompletionList *m_tree;
|
||||
QSize m_preferredSize;
|
||||
QPointer<QWidget> m_window;
|
||||
void updateWindow();
|
||||
LocatorWidget *m_inputWidget;
|
||||
};
|
||||
|
||||
LocatorWidget *createStaticLocatorWidget(Locator *locator);
|
||||
LocatorPopup *createLocatorPopup(Locator *locator, QWidget *parent);
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Core
|
||||
|
Reference in New Issue
Block a user