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.
24 #include <QStyleOption>
26 #include <kstringhandler.h>
30 #include "historyitem.h"
31 #include "popupproxy.h"
33 #include "klipperpopup.h"
36 PopupProxy::PopupProxy( KlipperPopup
* parent
, int menu_height
, int menu_width
)
38 proxy_for_menu( parent
),
39 spillPointer( parent
->history()->youngest() ),
40 m_menu_height( menu_height
),
41 m_menu_width( menu_width
),
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() {
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() );
66 int PopupProxy::buildParent( int index
, const QRegExp
& filter
) {
68 // Start from top of history (again)
69 spillPointer
= parent()->history()->youngest();
71 if ( filter
.isValid() ) {
75 return insertFromSpill( index
);
79 KlipperPopup
* PopupProxy::parent() {
80 return static_cast<KlipperPopup
*>( QObject::parent() );
83 void PopupProxy::slotAboutToShow() {
87 void PopupProxy::tryInsertItem( HistoryItem
const * const item
,
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
);
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
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
,
122 QSize( 0, fontheight
),
123 QStyleOption(mi
,10,0) ).height();
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()
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;
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
149 tryInsertItem( item
, remainingHeight
, index
++ );
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.
169 #include "popupproxy.moc"