Add (and install) svg for the new krunner interface.
[kdebase/uwolfer.git] / workspace / klipper / popupproxy.cpp
blob7bdbe1288bddd63b7d4f233bb6b074177ad159fa
1 // -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*-
2 /* This file is part of the KDE project
3 Copyright (C) 2004 Esben Mose Hansen <kde@mosehansen.dk>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
20 #include <QRegExp>
21 #include <QStyle>
22 #include <QPixmap>
23 #include <QImage>
24 #include <QStyleOption>
26 #include <kstringhandler.h>
27 #include <klocale.h>
28 #include <kdebug.h>
30 #include "historyitem.h"
31 #include "popupproxy.h"
32 #include "history.h"
33 #include "klipperpopup.h"
36 PopupProxy::PopupProxy( KlipperPopup* parent, int menu_height, int menu_width )
37 : QObject( parent ),
38 proxy_for_menu( parent ),
39 spillPointer( parent->history()->youngest() ),
40 m_menu_height( menu_height ),
41 m_menu_width( menu_width ),
42 nextItemNumber( 0 )
44 connect( parent->history(), SIGNAL( changed() ), SLOT( slotHistoryChanged() ) );
45 connect(proxy_for_menu, SIGNAL(triggered(QAction*)), parent->history(), SLOT(slotMoveToTop(QAction*)));
48 void PopupProxy::slotHistoryChanged() {
49 deleteMoreMenus();
53 void PopupProxy::deleteMoreMenus() {
54 const KMenu* myParent = parent();
55 if ( myParent != proxy_for_menu ) {
56 const KMenu* delme = proxy_for_menu;;
57 proxy_for_menu = static_cast<KMenu*>( proxy_for_menu->parent() );
58 while ( proxy_for_menu != myParent ) {
59 delme = proxy_for_menu;
60 proxy_for_menu = static_cast<KMenu*>( proxy_for_menu->parent() );
62 delete delme;
66 int PopupProxy::buildParent( int index, const QRegExp& filter ) {
67 deleteMoreMenus();
68 // Start from top of history (again)
69 spillPointer = parent()->history()->youngest();
70 nextItemNumber = 0;
71 if ( filter.isValid() ) {
72 m_filter = filter;
75 return insertFromSpill( index );
79 KlipperPopup* PopupProxy::parent() {
80 return static_cast<KlipperPopup*>( QObject::parent() );
83 void PopupProxy::slotAboutToShow() {
84 insertFromSpill();
87 void PopupProxy::tryInsertItem( HistoryItem const * const item,
88 int& remainingHeight,
89 const int index )
91 QAction *action = new QAction(this);
92 QPixmap image( item->image() );
93 if ( image.isNull() ) {
94 // Squeeze text strings so that do not take up the entire screen (or more)
95 QString text = proxy_for_menu->fontMetrics().elidedText( item->text().simplified(), Qt::ElideMiddle, m_menu_width );
96 text.replace( "&", "&&" );
97 action->setText(text);
98 } else {
99 const QSize max_size( m_menu_width,m_menu_height/4 );
100 if ( image.height() > max_size.height() || image.width() > max_size.width() ) {
101 image = image.scaled( max_size, Qt::KeepAspectRatio, Qt::SmoothTransformation );
103 action->setIcon(QIcon(image));
106 action->setData(nextItemNumber);
108 proxy_for_menu->insertAction(proxy_for_menu->actions().at(index), action);
110 // Determine height of a menu item.
112 int itemheight = QFontMetrics(proxy_for_menu->fontMetrics()).height();
114 //TODO Use old-style QStyle and QStyleOption API
115 #if 0
116 Q_ASSERT( id != -1 ); // Be sure that the item was inserted.
117 QMenuItem* mi = proxy_for_menu->findItem( id );
120 int itemheight = proxy_for_menu->style().sizeFromContents(QStyle::CT_PopupMenuItem,
121 proxy_for_menu,
122 QSize( 0, fontheight ),
123 QStyleOption(mi,10,0) ).height();
124 #endif
125 // Test if there was enough space
126 remainingHeight -= itemheight;
129 int PopupProxy::insertFromSpill( int index ) {
131 // This menu is going to be filled, so we don't need the aboutToShow()
132 // signal anymore
133 disconnect( proxy_for_menu, 0, this, 0 );
135 // Insert history items into the current proxy_for_menu,
136 // discarding any that doesn't match the current filter.
137 // stop when the total number of items equal m_itemsPerMenu;
138 int count = 0;
139 int remainingHeight = m_menu_height - proxy_for_menu->sizeHint().height();
140 // Force at least one item to be inserted.
141 remainingHeight = qMax( remainingHeight, 0 );
143 while (spillPointer.hasNext() && remainingHeight >= 0) {
144 const HistoryItem *item = spillPointer.next();
145 if ( m_filter.indexIn( item->text() ) == -1) {
146 nextItemNumber++; // also count hidden items
147 continue;
149 tryInsertItem( item, remainingHeight, index++ );
150 count++;
151 nextItemNumber++;
154 // If there is more items in the history, insert a new "More..." menu and
155 // make *this a proxy for that menu ('s content).
156 if (spillPointer.hasNext()) {
157 KMenu* moreMenu = new KMenu( proxy_for_menu );
158 QAction *menuAction = new QAction(i18n("&More"), this);
159 menuAction->setMenu(moreMenu);
160 connect(moreMenu, SIGNAL(aboutToShow()), SLOT(slotAboutToShow()));
161 proxy_for_menu->insertAction(proxy_for_menu->actions().at(index), menuAction);
162 proxy_for_menu = moreMenu;
165 // Return the number of items inserted.
166 return count;
169 #include "popupproxy.moc"