mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-24 19:02:51 +00:00
664 lines
24 KiB
C++
664 lines
24 KiB
C++
/***************************************************************************
|
|
* Copyright 2006 by Aaron Seigo <aseigo@kde.org> *
|
|
* Copyright 2008 by Davide Bettio <davide.bettio@kdemail.net> *
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
* This program is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU General Public License *
|
|
* along with this program; if not, write to the *
|
|
* Free Software Foundation, Inc., *
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA . *
|
|
***************************************************************************/
|
|
|
|
#include "interface.h"
|
|
|
|
#include <QAction>
|
|
#include <QApplication>
|
|
#include <QClipboard>
|
|
#include <QDesktopWidget>
|
|
#include <QGraphicsView>
|
|
#include <QHBoxLayout>
|
|
#include <QtGui/qevent.h>
|
|
#include <QLabel>
|
|
#include <QShortcut>
|
|
#include <QToolButton>
|
|
#include <QVBoxLayout>
|
|
|
|
#include <KAction>
|
|
#include <KActionCollection>
|
|
#include <KHistoryComboBox>
|
|
#include <KCompletion>
|
|
#include <KCompletionBox>
|
|
#include <KDebug>
|
|
#include <KDialog>
|
|
#include <KLineEdit>
|
|
#include <KLocale>
|
|
#include <KGlobalSettings>
|
|
#include <KPushButton>
|
|
#include <KStyle>
|
|
#include <KTitleWidget>
|
|
#include <KWindowSystem>
|
|
|
|
#include <Plasma/AbstractRunner>
|
|
#include <Plasma/RunnerManager>
|
|
#include <Plasma/Theme>
|
|
#include <Plasma/Svg>
|
|
|
|
#include "krunnerapp.h"
|
|
#include "krunnersettings.h"
|
|
#include "interfaces/default/resultscene.h"
|
|
#include "interfaces/default/resultitem.h"
|
|
#include "interfaces/default/krunnerhistorycombobox.h"
|
|
#include "interfaces/default/resultview.h"
|
|
#include "toolbutton.h"
|
|
|
|
static const int MIN_WIDTH = 420;
|
|
|
|
Interface::Interface(Plasma::RunnerManager *runnerManager, QWidget *parent)
|
|
: KRunnerDialog(runnerManager, parent),
|
|
m_delayedRun(false),
|
|
m_running(false),
|
|
m_queryRunning(false)
|
|
{
|
|
m_resultData.processHoverEvents = true;
|
|
m_resultData.mouseHovering = false;
|
|
m_resultData.runnerManager = runnerManager;
|
|
|
|
m_hideResultsTimer.setSingleShot(true);
|
|
connect(&m_hideResultsTimer, SIGNAL(timeout()), this, SLOT(hideResultsArea()));
|
|
|
|
m_reenableHoverEventsTimer.setSingleShot(true);
|
|
m_reenableHoverEventsTimer.setInterval(50);
|
|
connect(&m_reenableHoverEventsTimer, SIGNAL(timeout()), this, SLOT(reenableHoverEvents()));
|
|
|
|
m_layout = new QVBoxLayout(this);
|
|
m_layout->setMargin(0);
|
|
|
|
m_buttonContainer = new QWidget(this);
|
|
QHBoxLayout *bottomLayout = new QHBoxLayout(m_buttonContainer);
|
|
bottomLayout->setMargin(0);
|
|
|
|
m_configButton = new ToolButton(m_buttonContainer);
|
|
m_configButton->setText(i18n("Settings"));
|
|
m_configButton->setToolTip(i18n("Settings"));
|
|
connect(m_configButton, SIGNAL(clicked()), SLOT(toggleConfigDialog()));
|
|
bottomLayout->addWidget(m_configButton);
|
|
|
|
//Set up the system activity button, using the krunner global action, showing the global shortcut in the tooltip
|
|
m_activityButton = new ToolButton(m_buttonContainer);
|
|
KRunnerApp *krunnerApp = KRunnerApp::self();
|
|
QAction *showSystemActivityAction = krunnerApp->actionCollection()->action(QLatin1String( "Show System Activity" ));
|
|
m_activityButton->setDefaultAction(showSystemActivityAction);
|
|
|
|
updateSystemActivityToolTip();
|
|
connect(showSystemActivityAction, SIGNAL(globalShortcutChanged(QKeySequence)), this, SLOT(updateSystemActivityToolTip()));
|
|
connect(showSystemActivityAction, SIGNAL(triggered(bool)), this, SLOT(resetAndClose()));
|
|
bottomLayout->addWidget(m_activityButton);
|
|
|
|
m_singleRunnerIcon = new QLabel();
|
|
bottomLayout->addWidget(m_singleRunnerIcon);
|
|
m_singleRunnerDisplayName = new QLabel();
|
|
bottomLayout->addWidget(m_singleRunnerDisplayName);
|
|
|
|
m_helpButton = new ToolButton(m_buttonContainer);
|
|
m_helpButton->setText(i18n("Help"));
|
|
m_helpButton->setToolTip(i18n("Information on using this application"));
|
|
connect(m_helpButton, SIGNAL(clicked(bool)), SLOT(showHelp()));
|
|
connect(m_helpButton, SIGNAL(clicked(bool)), SLOT(configCompleted()));
|
|
bottomLayout->addWidget(m_helpButton);
|
|
|
|
QSpacerItem* closeButtonSpacer = new QSpacerItem(0,0,QSizePolicy::MinimumExpanding,QSizePolicy::Fixed);
|
|
bottomLayout->addSpacerItem(closeButtonSpacer);
|
|
|
|
m_closeButton = new ToolButton(m_buttonContainer);
|
|
KGuiItem guiItem = KStandardGuiItem::close();
|
|
m_closeButton->setText(guiItem.text());
|
|
m_closeButton->setToolTip(guiItem.text().remove(QLatin1Char( '&' )));
|
|
connect(m_closeButton, SIGNAL(clicked(bool)), SLOT(resetAndClose()));
|
|
bottomLayout->addWidget(m_closeButton);
|
|
|
|
m_layout->addWidget(m_buttonContainer);
|
|
|
|
m_searchTerm = new KrunnerHistoryComboBox(false, this);
|
|
|
|
KLineEdit *lineEdit = new KLineEdit(m_searchTerm);
|
|
QAction *focusEdit = new QAction(this);
|
|
focusEdit->setShortcut(Qt::Key_F6);
|
|
|
|
connect(focusEdit, SIGNAL(triggered(bool)), this, SLOT(searchTermSetFocus()));
|
|
addAction(focusEdit);
|
|
|
|
// the order of these next few lines if very important.
|
|
// QComboBox::setLineEdit sets the autoComplete flag on the lineedit,
|
|
// and KComboBox::setAutoComplete resets the autocomplete mode! ugh!
|
|
m_searchTerm->setLineEdit(lineEdit);
|
|
|
|
m_completion = new KCompletion();
|
|
lineEdit->setCompletionObject(m_completion);
|
|
lineEdit->setCompletionMode(static_cast<KGlobalSettings::Completion>(KRunnerSettings::queryTextCompletionMode()));
|
|
lineEdit->setClearButtonShown(true);
|
|
QStringList pastQueryItems = KRunnerSettings::pastQueries();
|
|
m_searchTerm->setHistoryItems(pastQueryItems);
|
|
m_completion->insertItems(pastQueryItems);
|
|
bottomLayout->insertWidget(4, m_searchTerm, 10);
|
|
|
|
m_singleRunnerSearchTerm = new KLineEdit(this);
|
|
bottomLayout->insertWidget(4, m_singleRunnerSearchTerm, 10 );
|
|
|
|
//kDebug() << "size:" << m_resultsView->size() << m_resultsView->minimumSize();
|
|
m_resultsScene = new ResultScene(&m_resultData, runnerManager, m_searchTerm, this);
|
|
m_resultsView = new ResultsView(m_resultsScene, &m_resultData, this);
|
|
m_layout->addWidget(m_resultsView);
|
|
|
|
connect(m_resultsScene, SIGNAL(viewableHeightChanged()), this, SLOT(fitWindow()));
|
|
connect(m_resultsScene, SIGNAL(matchCountChanged(int)), this, SLOT(matchCountChanged(int)));
|
|
connect(m_resultsScene, SIGNAL(itemActivated(ResultItem*)), this, SLOT(run(ResultItem*)));
|
|
|
|
connect(m_searchTerm, SIGNAL(queryTextEdited(QString)), this, SLOT(queryTextEdited(QString)));
|
|
connect(m_searchTerm, SIGNAL(returnPressed()), this, SLOT(runDefaultResultItem()));
|
|
connect(m_singleRunnerSearchTerm, SIGNAL(textChanged(QString)), this, SLOT(queryTextEdited(QString)));
|
|
connect(m_singleRunnerSearchTerm, SIGNAL(returnPressed()), this, SLOT(runDefaultResultItem()));
|
|
|
|
lineEdit->installEventFilter(this);
|
|
m_searchTerm->installEventFilter(this);
|
|
|
|
themeUpdated();
|
|
connect(Plasma::Theme::defaultTheme(), SIGNAL(themeChanged()), this, SLOT(themeUpdated()));
|
|
|
|
new QShortcut(QKeySequence(Qt::Key_Escape), this, SLOT(resetAndClose()));
|
|
|
|
m_layout->setAlignment(Qt::AlignTop);
|
|
|
|
setTabOrder(0, m_configButton);
|
|
setTabOrder(m_configButton, m_activityButton);
|
|
setTabOrder(m_activityButton, m_searchTerm);
|
|
setTabOrder(m_searchTerm, m_singleRunnerSearchTerm);
|
|
setTabOrder(m_singleRunnerSearchTerm, m_resultsView);
|
|
setTabOrder(m_resultsView, m_helpButton);
|
|
setTabOrder(m_helpButton, m_closeButton);
|
|
|
|
//kDebug() << "size:" << m_resultsView->size() << m_resultsView->minimumSize() << minimumSizeHint();
|
|
|
|
// we restore the original size, which will set the results view back to its
|
|
// normal size, then we hide the results view and resize the dialog
|
|
|
|
setMinimumSize(QSize(MIN_WIDTH, m_searchTerm->sizeHint().height()));
|
|
|
|
// we load the last used size; the saved value is the size of the dialog when the
|
|
// results are visible;
|
|
adjustSize();
|
|
|
|
if (KGlobal::config()->hasGroup("Interface")) {
|
|
KConfigGroup interfaceConfig(KGlobal::config(), "Interface");
|
|
restoreDialogSize(interfaceConfig);
|
|
m_defaultSize = size();
|
|
} else {
|
|
const int screenWidth = qApp->desktop()->screenGeometry().width();
|
|
int width = size().width();
|
|
|
|
if (screenWidth >= 1920) {
|
|
width = qMax(width, 550);
|
|
} else if (screenWidth >= 1024) {
|
|
width = qMax(width, 300);
|
|
}
|
|
|
|
m_defaultSize = QSize(width, 500);
|
|
}
|
|
|
|
m_resultsView->hide();
|
|
|
|
m_delayedQueryTimer.setSingleShot(true);
|
|
m_delayedQueryTimer.setInterval(50);
|
|
connect(&m_delayedQueryTimer, SIGNAL(timeout()), this, SLOT(delayedQueryLaunch()));
|
|
|
|
m_saveDialogSizeTimer.setSingleShot(true);
|
|
m_saveDialogSizeTimer.setInterval(1000);
|
|
connect(&m_saveDialogSizeTimer, SIGNAL(timeout()), SLOT(saveCurrentDialogSize()));
|
|
|
|
QTimer::singleShot(0, this, SLOT(resetInterface()));
|
|
}
|
|
|
|
bool Interface::eventFilter(QObject *obj, QEvent *event)
|
|
{
|
|
if (obj == m_searchTerm->lineEdit() && event->type() == QEvent::MouseButtonPress) {
|
|
if (KWindowSystem::activeWindow() != winId()) {
|
|
// this overcomes problems with click-to-focus and being a Dock window
|
|
KWindowSystem::forceActiveWindow(winId());
|
|
searchTermSetFocus();
|
|
}
|
|
} else if (obj == m_searchTerm && event->type() == QEvent::KeyPress) {
|
|
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
|
|
// the comparision between itemText(1) and the currentText is an artifact
|
|
// of KHistoryComboBox: it sets the combobox to index 1 when using arrow-down
|
|
// through entries after having arrow-up'd through them and hitting the
|
|
// last item ... which one would expect to be index 0. index 1 is _also_
|
|
// the first item in the history at other times, however, so we need to
|
|
// check if index 1 is indeed the actual item or if item 1 is not the same
|
|
// the current text. very, very odd. but it works. - aseigo.
|
|
if (ke->key() == Qt::Key_Down &&
|
|
(m_searchTerm->currentIndex() < 1 ||
|
|
(m_searchTerm->currentIndex() == 1 &&
|
|
m_searchTerm->itemText(1) != m_searchTerm->currentText()))) {
|
|
m_resultsView->setFocus();
|
|
}
|
|
}
|
|
|
|
return KRunnerDialog::eventFilter(obj, event);
|
|
}
|
|
|
|
void Interface::saveDialogSize(KConfigGroup &group)
|
|
{
|
|
group.writeEntry("Size", m_defaultSize);
|
|
}
|
|
|
|
void Interface::restoreDialogSize(KConfigGroup &group)
|
|
{
|
|
resize(group.readEntry("Size", size()));
|
|
}
|
|
|
|
void Interface::updateSystemActivityToolTip()
|
|
{
|
|
/* Set the tooltip for the Show System Activity button to include the global shortcut */
|
|
KRunnerApp *krunnerApp = KRunnerApp::self();
|
|
KAction *showSystemActivityAction = qobject_cast<KAction *>(krunnerApp->actionCollection()->action(QLatin1String( "Show System Activity" )));
|
|
if (showSystemActivityAction) {
|
|
QString shortcut = showSystemActivityAction->globalShortcut().toString();
|
|
if (shortcut.isEmpty()) {
|
|
m_activityButton->setToolTip( showSystemActivityAction->toolTip() );
|
|
} else {
|
|
m_activityButton->setToolTip( i18nc("tooltip, shortcut", "%1 (%2)", showSystemActivityAction->toolTip(), shortcut));
|
|
}
|
|
}
|
|
}
|
|
|
|
void Interface::setConfigWidget(QWidget *w)
|
|
{
|
|
const int screenId = qApp->desktop()->screenNumber(this);
|
|
const int maxHeight = qApp->desktop()->availableGeometry(screenId).height();
|
|
|
|
int left, top, right, bottom;
|
|
getContentsMargins(&left, &top, &right, &bottom);
|
|
const int padding = top + bottom + m_activityButton->height();
|
|
resize(width(), qMin(maxHeight, qMax(w->sizeHint().height() + padding, m_defaultSize.height())));
|
|
|
|
m_resultsView->hide();
|
|
m_searchTerm->setEnabled(false);
|
|
m_layout->addWidget(w);
|
|
|
|
connect(w, SIGNAL(destroyed(QObject*)), this, SLOT(configWidgetDestroyed()));
|
|
}
|
|
|
|
void Interface::configWidgetDestroyed()
|
|
{
|
|
QTimer::singleShot(0, this, SLOT(cleanupAfterConfigWidget()));
|
|
}
|
|
|
|
void Interface::cleanupAfterConfigWidget()
|
|
{
|
|
m_searchTerm->setEnabled(true);
|
|
resetInterface();
|
|
searchTermSetFocus();
|
|
}
|
|
|
|
void Interface::resizeEvent(QResizeEvent *event)
|
|
{
|
|
// We set m_defaultSize only when the event is spontaneous, i.e. when the user resizes the
|
|
// window, or if they are manually resizing it
|
|
if ((freeFloating() && event->spontaneous()) || manualResizing() != NotResizing) {
|
|
if (manualResizing() == HorizontalResizing) {
|
|
m_defaultSize = QSize(size().width(), m_defaultSize.height());
|
|
} else {
|
|
m_defaultSize = QSize(m_defaultSize.width(), size().height());
|
|
}
|
|
m_saveDialogSizeTimer.start();
|
|
}
|
|
|
|
m_resultsView->resize(m_buttonContainer->width(), m_resultsView->height());
|
|
m_resultsScene->setWidth(m_resultsView->width());
|
|
KRunnerDialog::resizeEvent(event);
|
|
}
|
|
|
|
void Interface::saveCurrentDialogSize()
|
|
{
|
|
KConfigGroup interfaceConfig(KGlobal::config(), "Interface");
|
|
saveDialogSize(interfaceConfig);
|
|
}
|
|
|
|
Interface::~Interface()
|
|
{
|
|
KRunnerSettings::setPastQueries(m_searchTerm->historyItems());
|
|
KRunnerSettings::setQueryTextCompletionMode(m_searchTerm->completionMode());
|
|
KRunnerSettings::self()->writeConfig();
|
|
|
|
// Before saving the size we resize to the default size, with the results container shown.
|
|
resize(m_defaultSize);
|
|
KConfigGroup interfaceConfig(KGlobal::config(), "Interface");
|
|
saveCurrentDialogSize();
|
|
KGlobal::config()->sync();
|
|
}
|
|
|
|
|
|
void Interface::searchTermSetFocus()
|
|
{
|
|
if (m_runnerManager->singleMode()) {
|
|
m_singleRunnerSearchTerm->setFocus();
|
|
} else {
|
|
m_searchTerm->setFocus();
|
|
}
|
|
}
|
|
|
|
|
|
void Interface::themeUpdated()
|
|
{
|
|
//reset the icons
|
|
m_helpButton->setIcon(m_iconSvg->pixmap(QLatin1String( "help" )));
|
|
m_configButton->setIcon(m_iconSvg->pixmap(QLatin1String( "configure" )));
|
|
m_activityButton->setIcon(m_iconSvg->pixmap(QLatin1String( "status" )));
|
|
m_closeButton->setIcon(m_iconSvg->pixmap(QLatin1String( "close" )));
|
|
}
|
|
|
|
void Interface::clearHistory()
|
|
{
|
|
m_searchTerm->clearHistory();
|
|
KRunnerSettings::setPastQueries(m_searchTerm->historyItems());
|
|
}
|
|
|
|
void Interface::display(const QString &term)
|
|
{
|
|
if (!term.isEmpty() || !isVisible() ||
|
|
m_runnerManager->singleMode() != m_singleRunnerIcon->isVisible()) {
|
|
resetInterface();
|
|
}
|
|
|
|
positionOnScreen();
|
|
searchTermSetFocus();
|
|
|
|
if (m_runnerManager->singleMode()) {
|
|
if (term.isEmpty()) {
|
|
// We need to manually trigger queryTextEdited, since
|
|
// with an empty query it won't be triggered; still we need it
|
|
// to launch the query
|
|
queryTextEdited(QString());
|
|
} else {
|
|
m_singleRunnerSearchTerm->setText(term);
|
|
}
|
|
} else if (!term.isEmpty()) {
|
|
m_searchTerm->setItemText(0, term);
|
|
m_searchTerm->setCurrentIndex(0);
|
|
} else {
|
|
m_searchTerm->reset();
|
|
}
|
|
}
|
|
|
|
void Interface::resetInterface()
|
|
{
|
|
setStaticQueryMode(false);
|
|
m_delayedRun = false;
|
|
m_searchTerm->setCurrentItem(QString(), true, 0);
|
|
m_singleRunnerSearchTerm->clear();
|
|
m_resultsScene->queryCleared();
|
|
if (!m_running) {
|
|
m_runnerManager->reset();
|
|
}
|
|
resetResultsArea();
|
|
m_minimumHeight = height();
|
|
}
|
|
|
|
void Interface::showHelp()
|
|
{
|
|
QMap<QString, Plasma::QueryMatch> matches;
|
|
QList<Plasma::AbstractRunner*> runnerList;
|
|
|
|
Plasma::AbstractRunner *singleRunner = m_runnerManager->singleModeRunner();
|
|
if (singleRunner) {
|
|
runnerList << singleRunner;
|
|
} else {
|
|
runnerList = m_runnerManager->runners();
|
|
}
|
|
|
|
|
|
foreach (Plasma::AbstractRunner *runner, runnerList) {
|
|
int count = 0;
|
|
QIcon icon(runner->icon());
|
|
if (icon.isNull()) {
|
|
icon = KIcon(QLatin1String( "system-run" ));
|
|
}
|
|
|
|
foreach (const Plasma::RunnerSyntax &syntax, runner->syntaxes()) {
|
|
Plasma::QueryMatch match(0);
|
|
match.setType(Plasma::QueryMatch::InformationalMatch);
|
|
match.setIcon(icon);
|
|
match.setText(syntax.exampleQueriesWithTermDescription().join(QLatin1String( ", " )));
|
|
match.setSubtext(syntax.description() + QLatin1Char( '\n' ) +
|
|
i18n("(From %1, %2)", runner->name(), runner->description()));
|
|
match.setData(syntax.exampleQueries().first());
|
|
matches.insert(runner->name() + QString::number(++count), match);
|
|
}
|
|
}
|
|
|
|
m_resultsScene->setQueryMatches(matches.values());
|
|
}
|
|
|
|
void Interface::setStaticQueryMode(bool staticQuery)
|
|
{
|
|
// don't show the search and other control buttons in the case of a static querymatch
|
|
const bool visible = !staticQuery;
|
|
Plasma::AbstractRunner *singleRunner = m_runnerManager->singleModeRunner();
|
|
m_configButton->setVisible(visible && !singleRunner);
|
|
m_activityButton->setVisible(visible && !singleRunner);
|
|
m_helpButton->setVisible(visible);
|
|
m_searchTerm->setVisible(visible && !singleRunner);
|
|
m_singleRunnerSearchTerm->setVisible(visible && singleRunner);
|
|
if (singleRunner) {
|
|
m_singleRunnerIcon->setPixmap(singleRunner->icon().pixmap(QSize(22, 22)));
|
|
m_singleRunnerDisplayName->setText(singleRunner->name());
|
|
}
|
|
m_singleRunnerIcon->setVisible(singleRunner);
|
|
m_singleRunnerDisplayName->setVisible(singleRunner);
|
|
}
|
|
|
|
void Interface::hideEvent(QHideEvent *e)
|
|
{
|
|
resetInterface();
|
|
KRunnerDialog::hideEvent(e);
|
|
}
|
|
|
|
void Interface::run(ResultItem *item)
|
|
{
|
|
if (!item || !item->isValid() || item->group() < Plasma::QueryMatch::PossibleMatch) {
|
|
m_delayedRun = true;
|
|
return;
|
|
}
|
|
|
|
kDebug() << item->name() << item->id();
|
|
m_delayedRun = false;
|
|
|
|
if (item->group() == Plasma::QueryMatch::InformationalMatch) {
|
|
QString info = item->data();
|
|
int editPos = info.length();
|
|
|
|
if (!info.isEmpty()) {
|
|
if (item->isQueryPrototype()) {
|
|
// lame way of checking to see if this is a Help Button generated match!
|
|
int index = info.indexOf(QLatin1String( ":q:" ));
|
|
|
|
if (index != -1) {
|
|
editPos = index;
|
|
info.replace(QLatin1String( ":q:" ), QLatin1String( "" ));
|
|
}
|
|
}
|
|
|
|
QStringList history = m_searchTerm->historyItems();
|
|
history.prepend(m_searchTerm->currentText().trimmed());
|
|
kDebug() << m_searchTerm->currentText() << history;
|
|
m_searchTerm->setHistoryItems(history);
|
|
m_searchTerm->setCurrentIndex(0);
|
|
m_searchTerm->lineEdit()->setText(info);
|
|
m_searchTerm->lineEdit()->setCursorPosition(editPos);
|
|
QApplication::clipboard()->setText(info);
|
|
}
|
|
return;
|
|
}
|
|
|
|
//TODO: check if run is succesful before adding the term to history
|
|
if ((item->group() == Plasma::QueryMatch::CompletionMatch) ||
|
|
(item->group() == Plasma::QueryMatch::PossibleMatch)) {
|
|
m_searchTerm->addToHistory(item->name());
|
|
} else {
|
|
m_searchTerm->addToHistory(m_searchTerm->currentText().trimmed());
|
|
}
|
|
|
|
m_running = true;
|
|
// must run the result first before clearing the interface
|
|
// in a way that will cause the results scene to be cleared and
|
|
// the RunnerManager to be cleared of context as a result
|
|
close();
|
|
item->run(m_runnerManager);
|
|
m_running = false;
|
|
|
|
resetInterface();
|
|
}
|
|
|
|
void Interface::resetAndClose()
|
|
{
|
|
resetInterface();
|
|
close();
|
|
}
|
|
|
|
|
|
void Interface::runDefaultResultItem()
|
|
{
|
|
if (m_queryRunning) {
|
|
m_delayedRun = true;
|
|
} else {
|
|
run(m_resultsScene->defaultResultItem());
|
|
}
|
|
}
|
|
|
|
void Interface::queryTextEdited(const QString &query)
|
|
{
|
|
if (query.isEmpty() || query.trimmed() != m_runnerManager->query()) {
|
|
// if the query is empty and the query is NOT what we are currently looking for ... then
|
|
// reset m_delayedRun. it does happen, however, that a search is being made already for the
|
|
// query text and this method gets called again, in which case we do NOT want to reset
|
|
// m_delayedRun
|
|
m_delayedRun = false;
|
|
}
|
|
|
|
if (query.isEmpty() && !m_runnerManager->singleMode()) {
|
|
m_delayedQueryTimer.stop();
|
|
resetInterface();
|
|
m_queryRunning = false;
|
|
} else {
|
|
m_delayedQueryTimer.start();
|
|
m_queryRunning = true;
|
|
}
|
|
}
|
|
|
|
void Interface::delayedQueryLaunch()
|
|
{
|
|
const QString query = (m_runnerManager->singleMode() ? m_singleRunnerSearchTerm->userText()
|
|
: static_cast<KLineEdit*>(m_searchTerm->lineEdit())->userText()).trimmed();
|
|
const QString runnerId = m_runnerManager->singleMode() ? m_runnerManager->singleModeRunnerId() : QString();
|
|
|
|
// we want to check if this is a new query or not for the later running of
|
|
// the default item
|
|
if (!query.isEmpty() || m_runnerManager->singleMode()) {
|
|
const bool newQuery = !query.isEmpty() && m_runnerManager->query() != query;
|
|
m_queryRunning = m_queryRunning || newQuery || !runnerId.isEmpty();
|
|
m_runnerManager->launchQuery(query, runnerId);
|
|
}
|
|
}
|
|
|
|
void Interface::matchCountChanged(int count)
|
|
{
|
|
m_queryRunning = false;
|
|
const bool show = count > 0;
|
|
m_hideResultsTimer.stop();
|
|
|
|
if (show && m_delayedRun) {
|
|
kDebug() << "delayed run with" << count << "items";
|
|
runDefaultResultItem();
|
|
return;
|
|
}
|
|
|
|
if (show) {
|
|
//kDebug() << "showing!" << minimumSizeHint();
|
|
if (!m_resultsView->isVisible()) {
|
|
fitWindow();
|
|
|
|
// Next 2 lines are a workaround to allow arrow
|
|
// keys navigation in krunner's result list.
|
|
// Patch submited in bugreport #211578
|
|
QEvent event(QEvent::WindowActivate);
|
|
QApplication::sendEvent(m_resultsView, &event);
|
|
|
|
m_resultsView->show();
|
|
}
|
|
//m_resultsScene->resize(m_resultsView->width(), qMax(m_resultsView->height(), int(m_resultsScene->height())));
|
|
//kDebug() << s << size();
|
|
} else {
|
|
//kDebug() << "hiding ... eventually";
|
|
m_delayedRun = false;
|
|
m_hideResultsTimer.start(1000);
|
|
}
|
|
}
|
|
|
|
void Interface::reenableHoverEvents()
|
|
{
|
|
//kDebug() << "reenabling hover events, for better or worse";
|
|
m_resultData.processHoverEvents = true;
|
|
}
|
|
|
|
void Interface::fitWindow()
|
|
{
|
|
m_resultData.processHoverEvents = false;
|
|
QSize s = m_defaultSize;
|
|
const int resultsHeight = m_resultsScene->viewableHeight() + 2;
|
|
int spacing = m_layout->spacing();
|
|
if (spacing < 0) {
|
|
// KStyles allow for variable spacing via the layoutSpacingImplementation() method;
|
|
// in this case m_layout->spacing() returns -1 and we should ask for the
|
|
// spacing by ourselves.
|
|
// This is quite ugly, but at least gives the right guess, so that we avoid
|
|
// multiple resize events
|
|
spacing = style()->layoutSpacing(QSizePolicy::DefaultType, QSizePolicy::DefaultType, Qt::Vertical);
|
|
}
|
|
|
|
//kDebug() << m_minimumHeight << resultsHeight << spacing << s.height();
|
|
|
|
if (m_minimumHeight + resultsHeight + spacing < s.height()) {
|
|
s.setHeight(m_minimumHeight + resultsHeight + spacing);
|
|
m_resultsView->setMinimumHeight(resultsHeight);
|
|
// The layout will activate on the next event cycle, but
|
|
// we need to update the minimum size now, as we are going to
|
|
// resize the krunner window right away.
|
|
m_layout->activate();
|
|
}
|
|
|
|
resize(s);
|
|
m_reenableHoverEventsTimer.start();
|
|
}
|
|
|
|
void Interface::hideResultsArea()
|
|
{
|
|
searchTermSetFocus();
|
|
resetResultsArea();
|
|
}
|
|
|
|
void Interface::resetResultsArea()
|
|
{
|
|
m_resultsView->hide();
|
|
setMinimumSize(QSize(MIN_WIDTH, m_searchTerm->sizeHint().height()));
|
|
resize(qMax(minimumSizeHint().width(), m_defaultSize.width()), minimumSizeHint().height());
|
|
}
|
|
|
|
#include "moc_interface.cpp"
|