diff --git a/app/ToolTips/ktooltip.cpp b/app/ToolTips/ktooltip.cpp index 99114106..34561f1c 100644 --- a/app/ToolTips/ktooltip.cpp +++ b/app/ToolTips/ktooltip.cpp @@ -1,102 +1,105 @@ /*************************************************************************** * Copyright (C) 2008 by Fredrik Höglund * * * * 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 "ktooltip.h" #include "ktooltipwindow_p.h" #include #include +#include #include class KToolTipManager { public: ~KToolTipManager(); static KToolTipManager* instance(); - void showTip(const QPoint& pos, QWidget* content); + void showTip(const QPoint& pos, QWidget* content, QWindow *transientParent); void hideTip(); private: KToolTipManager(); KToolTipWindow* m_window; static KToolTipManager *s_instance; }; KToolTipManager *KToolTipManager::s_instance = 0; KToolTipManager::KToolTipManager() : m_window(0) { } KToolTipManager::~KToolTipManager() { delete m_window; m_window = 0; } KToolTipManager* KToolTipManager::instance() { if (s_instance == 0) { s_instance = new KToolTipManager(); } return s_instance; } -void KToolTipManager::showTip(const QPoint& pos, QWidget* content) +void KToolTipManager::showTip(const QPoint& pos, QWidget* content, QWindow *transientParent) { hideTip(); Q_ASSERT(m_window == 0); m_window = new KToolTipWindow(content); m_window->move(pos); + m_window->createWinId(); + m_window->windowHandle()->setTransientParent(transientParent); m_window->show(); } void KToolTipManager::hideTip() { if (m_window != 0) { m_window->hide(); m_window->deleteLater(); m_window = 0; } } namespace KToolTip { - void showText(const QPoint& pos, const QString& text) + void showText(const QPoint& pos, const QString& text, QWindow *transientParent) { QLabel* label = new QLabel(text); label->setForegroundRole(QPalette::ToolTipText); - showTip(pos, label); + showTip(pos, label, transientParent); } - void showTip(const QPoint& pos, QWidget* content) + void showTip(const QPoint& pos, QWidget* content, QWindow *transientParent) { - KToolTipManager::instance()->showTip(pos, content); + KToolTipManager::instance()->showTip(pos, content, transientParent); } void hideTip() { KToolTipManager::instance()->hideTip(); } } diff --git a/app/ToolTips/ktooltip.h b/app/ToolTips/ktooltip.h index bd539b83..82ed45e7 100644 --- a/app/ToolTips/ktooltip.h +++ b/app/ToolTips/ktooltip.h @@ -1,46 +1,47 @@ /*************************************************************************** * Copyright (C) 2008 by Fredrik Höglund * * * * 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 * ***************************************************************************/ #ifndef KTOOLTIP_H #define KTOOLTIP_H class QPoint; class QString; class QWidget; +class QWindow; /** * Allows to show tooltips having a widget as content. */ namespace KToolTip { - void showText(const QPoint& pos, const QString& text); + void showText(const QPoint& pos, const QString& text, QWindow *transientParent); /** * Shows the tip @p content at the global position indicated by @p pos. * * Ownership of the content widget is transferred to KToolTip. The widget will be deleted * automatically when it is hidden. * * The tip is shown immediately when this function is called. */ - void showTip(const QPoint& pos, QWidget* content); + void showTip(const QPoint& pos, QWidget* content, QWindow *transientParent); void hideTip(); } #endif diff --git a/app/ToolTips/tooltipmanager.cpp b/app/ToolTips/tooltipmanager.cpp index 1f7e5556..f2f9943c 100644 --- a/app/ToolTips/tooltipmanager.cpp +++ b/app/ToolTips/tooltipmanager.cpp @@ -1,247 +1,247 @@ /******************************************************************************* * Copyright (C) 2008 by Konstantin Heil * * * * 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 "tooltipmanager.h" #include "MenuItem.h" #include "ktooltip.h" #include #include #include #include #include #include #include #include #include #include #include class ToolTipManager::Private { public: Private() : view(0), timer(0) { } QAbstractItemView* view; QTimer* timer; QModelIndex item; QRect itemRect; }; ToolTipManager::ToolTipManager(QAbstractItemView* parent) : QObject(parent) , d(new ToolTipManager::Private) { d->view = parent; connect(parent, &QAbstractItemView::viewportEntered, this, &ToolTipManager::hideToolTip); connect(parent, &QAbstractItemView::entered, this, &ToolTipManager::requestToolTip); d->timer = new QTimer(this); d->timer->setSingleShot(true); connect(d->timer, &QTimer::timeout, this, &ToolTipManager::prepareToolTip); // When the mousewheel is used, the items don't get a hovered indication // (Qt-issue #200665). To assure that the tooltip still gets hidden, // the scrollbars are observed. connect(parent->horizontalScrollBar(), &QAbstractSlider::valueChanged, this, &ToolTipManager::hideToolTip); connect(parent->verticalScrollBar(), &QAbstractSlider::valueChanged, this, &ToolTipManager::hideToolTip); d->view->viewport()->installEventFilter(this); } ToolTipManager::~ToolTipManager() { delete d; } bool ToolTipManager::eventFilter(QObject* watched, QEvent* event) { if ( watched == d->view->viewport() ) { switch ( event->type() ) { case QEvent::Leave: case QEvent::MouseButtonPress: hideToolTip(); break; case QEvent::ToolTip: return true; default: break; } } return QObject::eventFilter(watched, event); } void ToolTipManager::requestToolTip(const QModelIndex& index) { // only request a tooltip for the name column and when no selection or // drag & drop operation is done (indicated by the left mouse button) if ( !(QApplication::mouseButtons() & Qt::LeftButton) ) { KToolTip::hideTip(); d->itemRect = d->view->visualRect(index); const QPoint pos = d->view->viewport()->mapToGlobal(d->itemRect.topLeft()); d->itemRect.moveTo(pos); d->item = index; d->timer->start(300); } else { hideToolTip(); } } void ToolTipManager::hideToolTip() { d->timer->stop(); KToolTip::hideTip(); } void ToolTipManager::prepareToolTip() { showToolTip( d->item ); } void ToolTipManager::showToolTip( QModelIndex menuItem ) { if (QApplication::mouseButtons() & Qt::LeftButton) { return; } QWidget * tip = createTipContent( menuItem ); // calculate the x- and y-position of the tooltip const QSize size = tip->sizeHint(); const QRect desktop = QApplication::desktop()->screenGeometry( d->itemRect.bottomRight() ); // d->itemRect defines the area of the item, where the tooltip should be // shown. Per default the tooltip is shown in the bottom right corner. // If the tooltip content exceeds the desktop borders, it must be assured that: // - the content is fully visible // - the content is not drawn inside d->itemRect const int margin = 3; const bool hasRoomToLeft = (d->itemRect.left() - size.width() - margin >= desktop.left()); const bool hasRoomToRight = (d->itemRect.right() + size.width() + margin <= desktop.right()); const bool hasRoomAbove = (d->itemRect.top() - size.height() - margin >= desktop.top()); const bool hasRoomBelow = (d->itemRect.bottom() + size.height() + margin <= desktop.bottom()); if (!hasRoomAbove && !hasRoomBelow && !hasRoomToLeft && !hasRoomToRight) { delete tip; tip = 0; return; } int x = 0; int y = 0; if (hasRoomBelow || hasRoomAbove) { x = qMax(desktop.left(), d->itemRect.center().x() - size.width() / 2); if (x + size.width() / 2 >= desktop.right()) { x = desktop.right() - size.width(); } y = hasRoomBelow ? d->itemRect.bottom() + margin : d->itemRect.top() - size.height() - margin; } else { Q_ASSERT(hasRoomToLeft || hasRoomToRight); x = hasRoomToRight ? d->itemRect.right() + margin : d->itemRect.left() - size.width() - margin; // Put the tooltip at the bottom of the screen. The x-coordinate has already // been adjusted, so that no overlapping with d->itemRect occurs. y = desktop.bottom() - size.height(); } // the ownership of tip is transferred to KToolTip - KToolTip::showTip(QPoint(x, y), tip); + KToolTip::showTip(QPoint(x, y), tip, d->view->nativeParentWidget()->windowHandle()); } QWidget * ToolTipManager::createTipContent( QModelIndex item ) { const QSize dialogIconSize = QSize(IconSize(KIconLoader::Dialog), IconSize(KIconLoader::Dialog)); const QSize toolbarIconSize = QSize(IconSize(KIconLoader::MainToolbar), IconSize(KIconLoader::MainToolbar)); QWidget * tipContent = new QWidget(); QGridLayout* tipLayout = new QGridLayout(); tipLayout->setAlignment( Qt::AlignLeft ); QLayout * primaryLine = generateToolTipLine( &item, tipContent, dialogIconSize, true ); primaryLine->setAlignment( Qt::AlignLeft ); tipLayout->addLayout( primaryLine, 0, 0, Qt::AlignLeft ); for ( int done = 0; d->view->model()->rowCount( item ) > done; done = 1 + done ) { QModelIndex childItem = d->view->model()->index( done, 0, item ); QLayout * subLine = generateToolTipLine( &childItem, tipContent, toolbarIconSize, false ); subLine->setAlignment( Qt::AlignLeft ); tipLayout->addLayout( subLine, done + 2, 0, Qt::AlignLeft ); } tipLayout->setVerticalSpacing( tipContent->fontMetrics().height() / 3 ); tipContent->setLayout( tipLayout ); if( d->view->model()->rowCount( item ) > 0 ) { QFrame * separatorLine = new QFrame( tipContent ); separatorLine->setFrameStyle( QFrame::HLine ); tipLayout->addWidget( separatorLine, 1, 0 ); } return tipContent; } QLayout * ToolTipManager::generateToolTipLine( QModelIndex * item, QWidget * toolTip, QSize iconSize, bool comment ) { // Get MenuItem MenuItem * menuItem = d->view->model()->data( *item, Qt::UserRole ).value(); QString text = menuItem->name(); if ( comment ) { text = QString( "%1" ).arg( menuItem->name() ); } // Generate text if ( comment ) { text += "
"; if ( !menuItem->service()->comment().isEmpty() ) { text += menuItem->service()->comment(); } else { int childCount = d->view->model()->rowCount( *item ); text += i18np( "Contains 1 item", "Contains %1 items", childCount ); } } QLabel * textLabel = new QLabel( toolTip ); textLabel->setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ); textLabel->setForegroundRole(QPalette::ToolTipText); textLabel->setText( text ); // Get icon QLabel * iconLabel = new QLabel( toolTip ); iconLabel->setPixmap( QIcon::fromTheme(menuItem->service()->icon()).pixmap(iconSize) ); iconLabel->setMaximumSize( iconSize ); // Generate layout QHBoxLayout * layout = new QHBoxLayout(); layout->setSpacing( textLabel->fontMetrics().height() / 3 ); layout->setAlignment( Qt::AlignLeft ); layout->addWidget( iconLabel, Qt::AlignLeft ); layout->addWidget( textLabel, Qt::AlignLeft ); return layout; }