source: psi/trunk/libpsi/psiwidgets/fancypopup.cpp@ 14

Last change on this file since 14 was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 9.4 KB
Line 
1/*
2 * fancypopup.cpp - the FancyPopup passive popup widget
3 * Copyright (C) 2003 Michail Pishchagin
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library 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 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include "fancypopup.h"
22
23#include <qpixmap.h>
24#include <qapplication.h>
25#include <qlabel.h>
26#include <qlayout.h>
27#include <qtimer.h>
28#include <qtooltip.h>
29#include <qpointarray.h>
30#include <qpainter.h>
31#include <qptrlist.h>
32#include <qtoolbutton.h>
33#include <qstyle.h>
34
35#include "iconset.h"
36#include "fancylabel.h"
37
38#define BUTTON_WIDTH 16
39#define BUTTON_HEIGHT 14
40
41/*static int checkComponent(int b)
42{
43 int c = b;
44 if ( c > 0xFF )
45 c = 0xFF;
46 return c;
47}
48
49static QColor makeColor(QColor baseColor, int percent)
50{
51 float p = (float)percent/100;
52 int r = checkComponent( (int)(baseColor.red() + ((float)p * baseColor.red())) );
53 int g = checkComponent( (int)(baseColor.green() + ((float)p * baseColor.green())) );
54 int b = checkComponent( (int)(baseColor.blue() + ((float)p * baseColor.blue())) );
55
56 return QColor(r, g, b);
57}*/
58
59//----------------------------------------------------------------------------
60// FancyPopup::Private
61//----------------------------------------------------------------------------
62
63class FancyPopup::Private : public QObject
64{
65 Q_OBJECT
66public:
67 Private(FancyPopup *p);
68 ~Private();
69
70 QPoint position();
71
72public slots:
73 void hide();
74 void popupDestroyed(QObject *);
75
76public:
77 // parameters
78 static int hideTimeout;
79 static QColor backgroundColor;
80
81 enum PopupLayout {
82 TopToBottom = 1,
83 BottomToTop = -1
84 };
85 PopupLayout popupLayout;
86
87 QPtrList<FancyPopup> prevPopups, nextPopups;
88 QBoxLayout *layout;
89 FancyPopup *popup;
90 QTimer *hideTimer;
91};
92
93int FancyPopup::Private::hideTimeout = 5 * 1000; // 5 seconds
94QColor FancyPopup::Private::backgroundColor = QColor (0x52, 0x97, 0xF9);
95
96FancyPopup::Private::Private(FancyPopup *p)
97: QObject(p)
98{
99 popup = p;
100
101 hideTimer = new QTimer(this);
102 connect(hideTimer, SIGNAL(timeout()), SLOT(hide()));
103}
104
105FancyPopup::Private::~Private()
106{
107}
108
109void FancyPopup::Private::hide()
110{
111 popup->hide();
112}
113
114void FancyPopup::Private::popupDestroyed(QObject *obj)
115{
116 if ( prevPopups.contains((FancyPopup *)obj) ) {
117 prevPopups.remove((FancyPopup *)obj);
118 popup->move( position() );
119 }
120 else if ( nextPopups.contains((FancyPopup *)obj) ) {
121 nextPopups.remove((FancyPopup *)obj);
122 }
123}
124
125QPoint FancyPopup::Private::position()
126{
127 QRect geom = qApp->desktop()->availableGeometry(popup);
128 QPoint destination(geom.x() + geom.width(), geom.y() + geom.height()); // in which corner popup should appear
129
130 if ( destination.y() > (qApp->desktop()->screenGeometry().height()/2) )
131 popupLayout = Private::BottomToTop;
132 else
133 popupLayout = Private::TopToBottom;
134
135 if ( (destination.x() + popup->width()) > (geom.x() + geom.width()) )
136 destination.setX( geom.x() + geom.width() - popup->width() );
137
138 if ( destination.x() < 0 )
139 destination.setX( 0 );
140
141 if ( (destination.y() + popup->height()) > (geom.y() + geom.height()) )
142 destination.setY( geom.y() + geom.height() - popup->height() );
143
144 if ( destination.y() < 0 )
145 destination.setY( 0 );
146
147 QPtrListIterator<FancyPopup> it ( prevPopups );
148 FancyPopup *p;
149 for ( ; (p = it.current()); ++it) {
150 destination.setY( destination.y() + popupLayout * p->height() );
151 }
152
153 return destination;
154}
155
156//----------------------------------------------------------------------------
157// FancyPopup
158//----------------------------------------------------------------------------
159
160static const int POPUP_FLAGS = Qt::WStyle_Customize | Qt::WDestructiveClose | Qt::WX11BypassWM
161 | Qt::WStyle_StaysOnTop | Qt::WStyle_Tool | Qt::WStyle_NoBorder;
162
163FancyPopup::FancyPopup(QString title, const Icon *icon, FancyPopup *prev, bool copyIcon)
164: QFrame( 0, 0, POPUP_FLAGS | WRepaintNoErase | WResizeNoErase | WDestructiveClose )
165{
166 d = new Private(this);
167
168 if ( prev ) {
169 QPtrListIterator<FancyPopup> it ( prev->d->prevPopups );
170 FancyPopup *popup;
171 bool finished = false;
172 for ( ; !finished; ++it) {
173 popup = it.current();
174 if ( !popup ) {
175 popup = prev;
176 finished = true;
177 }
178
179 d->prevPopups.append( popup );
180 connect(popup, SIGNAL(destroyed(QObject *)), d, SLOT(popupDestroyed(QObject *)));
181 }
182
183 prev->d->nextPopups.append( this );
184 connect(this, SIGNAL(destroyed(QObject *)), prev->d, SLOT(popupDestroyed(QObject *)));
185 }
186
187 // TODO: use darker color on popup borders
188 QPixmap back(1, 1);
189 QPainter p(&back);
190 p.setPen( d->backgroundColor );
191 p.drawPoint( 0, 0 );
192 p.end();
193
194 QVBoxLayout *vbox = new QVBoxLayout(this, 0, 0);
195
196 // top row
197 QHBoxLayout *tophbox = new QHBoxLayout(vbox);
198 QLabel *top1 = new QLabel(this);
199 top1->setFixedWidth(3);
200 top1->setPaletteBackgroundPixmap(back);
201 tophbox->addWidget(top1);
202
203 QVBoxLayout *topvbox = new QVBoxLayout(tophbox);
204 QLabel *top2 = new QLabel(this);
205 top2->setFixedHeight(1);
206 top2->setPaletteBackgroundPixmap(back);
207 topvbox->addWidget(top2);
208
209 QHBoxLayout *tophbox2 = new QHBoxLayout(topvbox);
210 IconLabel *titleIcon = new IconLabel(this);
211 titleIcon->setIcon(icon, copyIcon);
212 titleIcon->setPaletteBackgroundPixmap(back);
213 tophbox2->addWidget(titleIcon);
214
215 QLabel *top5 = new QLabel(this);
216 top5->setFixedWidth(3);
217 top5->setPaletteBackgroundPixmap(back);
218 tophbox2->addWidget(top5);
219
220 QLabel *titleText = new QLabel(this);
221 QString backgroundColorStr;
222 if ( (d->backgroundColor.red() + d->backgroundColor.green() + d->backgroundColor.blue())/3 > 128 )
223 backgroundColorStr = "white";
224 else
225 backgroundColorStr = "black";
226 titleText->setText( QString("<font color='%1'><nobr><b>%1</b></nobr></font>").arg( backgroundColorStr ).arg(title) );
227 titleText->setBackgroundPixmap(back);
228 titleText->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
229 tophbox2->addWidget(titleText);
230
231 QWidget *closeButtonBack = new QWidget(this);
232 closeButtonBack->setPaletteBackgroundPixmap( back );
233 tophbox2->addWidget(closeButtonBack);
234
235 QVBoxLayout *closeButtonBackLayout = new QVBoxLayout(closeButtonBack);
236 closeButtonBackLayout->addStretch();
237
238 QToolButton *closeButton = new QToolButton( closeButtonBack, "close" );
239 QToolTip::add( closeButton, tr( "Close" ) );
240 closeButtonBackLayout->addWidget( closeButton );
241 closeButtonBackLayout->addStretch();
242 closeButton->setFocusPolicy( NoFocus );
243 closeButton->setIconSet( style().stylePixmap(QStyle::SP_TitleBarCloseButton) );
244 closeButton->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT);
245 connect(closeButton, SIGNAL(clicked()), SLOT(hide()));
246
247 QLabel *top3 = new QLabel(this);
248 top3->setFixedHeight(1);
249 top3->setPaletteBackgroundPixmap(back);
250 topvbox->addWidget(top3);
251
252 QLabel *top4 = new QLabel(this);
253 top4->setFixedWidth(3);
254 top4->setPaletteBackgroundPixmap(back);
255 tophbox->addWidget(top4);
256
257 // middle row
258 QHBoxLayout *middlehbox = new QHBoxLayout(vbox);
259 QLabel *middle1 = new QLabel(this);
260 middle1->setFixedWidth(4);
261 middle1->setPaletteBackgroundPixmap(back);
262 middlehbox->addWidget(middle1);
263
264 middlehbox->addSpacing(5);
265 QVBoxLayout *middlevbox = new QVBoxLayout(middlehbox);
266 middlevbox->addSpacing(5);
267 d->layout = middlevbox; // we'll add more items later in addLayout()
268 middlehbox->addSpacing(5);
269
270 QLabel *middle3 = new QLabel(this);
271 middle3->setFixedWidth(4);
272 middle3->setPaletteBackgroundPixmap(back);
273 middlehbox->addWidget(middle3);
274
275 // bottom row
276 QHBoxLayout *bottomhbox = new QHBoxLayout(vbox);
277 QLabel *bottom1 = new QLabel(this);
278 bottom1->setFixedSize( 4, 4 );
279 bottom1->setPaletteBackgroundPixmap(back);
280 bottomhbox->addWidget(bottom1);
281
282 QLabel *bottom2 = new QLabel(this);
283 bottom2->setFixedHeight(4);
284 bottom2->setPaletteBackgroundPixmap(back);
285 bottomhbox->addWidget(bottom2);
286
287 QLabel *bottom3 = new QLabel(this);
288 bottom3->setFixedSize( 4, 4 );
289 bottom3->setPaletteBackgroundPixmap(back);
290 bottomhbox->addWidget(bottom3);
291}
292
293FancyPopup::~FancyPopup()
294{
295}
296
297void FancyPopup::addLayout(QLayout *layout, int stretch)
298{
299 d->layout->addLayout(layout, stretch);
300 d->layout->addSpacing(5);
301}
302
303void FancyPopup::show()
304{
305 if ( size() != sizeHint() )
306 resize( sizeHint() ); // minimumSizeHint()
307
308 // position popup
309 move ( d->position() );
310
311 // display popup
312 d->hideTimer->start( d->hideTimeout );
313 QFrame::show();
314}
315
316void FancyPopup::hideEvent(QHideEvent *e)
317{
318 d->hideTimer->stop();
319 deleteLater();
320
321 QFrame::hideEvent(e);
322}
323
324void FancyPopup::mouseReleaseEvent(QMouseEvent *e)
325{
326 QWidget *closeButton = (QWidget *)child("closeButton");
327 if ( closeButton ) {
328 QPoint p = closeButton->mapFromParent( e->pos() );
329 if ( p.x() >= 0 && p.y() >= 0 && p.x() < closeButton->width() && p.y() < closeButton->height() )
330 QFrame::mouseReleaseEvent(e);
331 }
332
333 emit clicked();
334 emit clicked((int)e->button());
335}
336
337void FancyPopup::restartHideTimer()
338{
339 d->hideTimer->stop();
340 d->hideTimer->start( d->hideTimeout );
341}
342
343void FancyPopup::setHideTimeout(int time)
344{
345 FancyPopup::Private::hideTimeout = time;
346}
347
348void FancyPopup::setBorderColor(QColor c)
349{
350 FancyPopup::Private::backgroundColor = c;
351}
352
353#include "fancypopup.moc"
Note: See TracBrowser for help on using the repository browser.