/* * fancypopup.cpp - the FancyPopup passive popup widget * Copyright (C) 2003 Michail Pishchagin * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */ #include "fancypopup.h" #include #include #include #include #include #include #include #include #include #include #include #include "iconset.h" #include "fancylabel.h" #define BUTTON_WIDTH 16 #define BUTTON_HEIGHT 14 /*static int checkComponent(int b) { int c = b; if ( c > 0xFF ) c = 0xFF; return c; } static QColor makeColor(QColor baseColor, int percent) { float p = (float)percent/100; int r = checkComponent( (int)(baseColor.red() + ((float)p * baseColor.red())) ); int g = checkComponent( (int)(baseColor.green() + ((float)p * baseColor.green())) ); int b = checkComponent( (int)(baseColor.blue() + ((float)p * baseColor.blue())) ); return QColor(r, g, b); }*/ //---------------------------------------------------------------------------- // FancyPopup::Private //---------------------------------------------------------------------------- class FancyPopup::Private : public QObject { Q_OBJECT public: Private(FancyPopup *p); ~Private(); QPoint position(); public slots: void hide(); void popupDestroyed(QObject *); public: // parameters static int hideTimeout; static QColor backgroundColor; enum PopupLayout { TopToBottom = 1, BottomToTop = -1 }; PopupLayout popupLayout; QPtrList prevPopups, nextPopups; QBoxLayout *layout; FancyPopup *popup; QTimer *hideTimer; }; int FancyPopup::Private::hideTimeout = 5 * 1000; // 5 seconds QColor FancyPopup::Private::backgroundColor = QColor (0x52, 0x97, 0xF9); FancyPopup::Private::Private(FancyPopup *p) : QObject(p) { popup = p; hideTimer = new QTimer(this); connect(hideTimer, SIGNAL(timeout()), SLOT(hide())); } FancyPopup::Private::~Private() { } void FancyPopup::Private::hide() { popup->hide(); } void FancyPopup::Private::popupDestroyed(QObject *obj) { if ( prevPopups.contains((FancyPopup *)obj) ) { prevPopups.remove((FancyPopup *)obj); popup->move( position() ); } else if ( nextPopups.contains((FancyPopup *)obj) ) { nextPopups.remove((FancyPopup *)obj); } } QPoint FancyPopup::Private::position() { QRect geom = qApp->desktop()->availableGeometry(popup); QPoint destination(geom.x() + geom.width(), geom.y() + geom.height()); // in which corner popup should appear if ( destination.y() > (qApp->desktop()->screenGeometry().height()/2) ) popupLayout = Private::BottomToTop; else popupLayout = Private::TopToBottom; if ( (destination.x() + popup->width()) > (geom.x() + geom.width()) ) destination.setX( geom.x() + geom.width() - popup->width() ); if ( destination.x() < 0 ) destination.setX( 0 ); if ( (destination.y() + popup->height()) > (geom.y() + geom.height()) ) destination.setY( geom.y() + geom.height() - popup->height() ); if ( destination.y() < 0 ) destination.setY( 0 ); QPtrListIterator it ( prevPopups ); FancyPopup *p; for ( ; (p = it.current()); ++it) { destination.setY( destination.y() + popupLayout * p->height() ); } return destination; } //---------------------------------------------------------------------------- // FancyPopup //---------------------------------------------------------------------------- static const int POPUP_FLAGS = Qt::WStyle_Customize | Qt::WDestructiveClose | Qt::WX11BypassWM | Qt::WStyle_StaysOnTop | Qt::WStyle_Tool | Qt::WStyle_NoBorder; FancyPopup::FancyPopup(QString title, const Icon *icon, FancyPopup *prev, bool copyIcon) : QFrame( 0, 0, POPUP_FLAGS | WRepaintNoErase | WResizeNoErase | WDestructiveClose ) { d = new Private(this); if ( prev ) { QPtrListIterator it ( prev->d->prevPopups ); FancyPopup *popup; bool finished = false; for ( ; !finished; ++it) { popup = it.current(); if ( !popup ) { popup = prev; finished = true; } d->prevPopups.append( popup ); connect(popup, SIGNAL(destroyed(QObject *)), d, SLOT(popupDestroyed(QObject *))); } prev->d->nextPopups.append( this ); connect(this, SIGNAL(destroyed(QObject *)), prev->d, SLOT(popupDestroyed(QObject *))); } // TODO: use darker color on popup borders QPixmap back(1, 1); QPainter p(&back); p.setPen( d->backgroundColor ); p.drawPoint( 0, 0 ); p.end(); QVBoxLayout *vbox = new QVBoxLayout(this, 0, 0); // top row QHBoxLayout *tophbox = new QHBoxLayout(vbox); QLabel *top1 = new QLabel(this); top1->setFixedWidth(3); top1->setPaletteBackgroundPixmap(back); tophbox->addWidget(top1); QVBoxLayout *topvbox = new QVBoxLayout(tophbox); QLabel *top2 = new QLabel(this); top2->setFixedHeight(1); top2->setPaletteBackgroundPixmap(back); topvbox->addWidget(top2); QHBoxLayout *tophbox2 = new QHBoxLayout(topvbox); IconLabel *titleIcon = new IconLabel(this); titleIcon->setIcon(icon, copyIcon); titleIcon->setPaletteBackgroundPixmap(back); tophbox2->addWidget(titleIcon); QLabel *top5 = new QLabel(this); top5->setFixedWidth(3); top5->setPaletteBackgroundPixmap(back); tophbox2->addWidget(top5); QLabel *titleText = new QLabel(this); QString backgroundColorStr; if ( (d->backgroundColor.red() + d->backgroundColor.green() + d->backgroundColor.blue())/3 > 128 ) backgroundColorStr = "white"; else backgroundColorStr = "black"; titleText->setText( QString("%1").arg( backgroundColorStr ).arg(title) ); titleText->setBackgroundPixmap(back); titleText->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); tophbox2->addWidget(titleText); QWidget *closeButtonBack = new QWidget(this); closeButtonBack->setPaletteBackgroundPixmap( back ); tophbox2->addWidget(closeButtonBack); QVBoxLayout *closeButtonBackLayout = new QVBoxLayout(closeButtonBack); closeButtonBackLayout->addStretch(); QToolButton *closeButton = new QToolButton( closeButtonBack, "close" ); QToolTip::add( closeButton, tr( "Close" ) ); closeButtonBackLayout->addWidget( closeButton ); closeButtonBackLayout->addStretch(); closeButton->setFocusPolicy( NoFocus ); closeButton->setIconSet( style().stylePixmap(QStyle::SP_TitleBarCloseButton) ); closeButton->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT); connect(closeButton, SIGNAL(clicked()), SLOT(hide())); QLabel *top3 = new QLabel(this); top3->setFixedHeight(1); top3->setPaletteBackgroundPixmap(back); topvbox->addWidget(top3); QLabel *top4 = new QLabel(this); top4->setFixedWidth(3); top4->setPaletteBackgroundPixmap(back); tophbox->addWidget(top4); // middle row QHBoxLayout *middlehbox = new QHBoxLayout(vbox); QLabel *middle1 = new QLabel(this); middle1->setFixedWidth(4); middle1->setPaletteBackgroundPixmap(back); middlehbox->addWidget(middle1); middlehbox->addSpacing(5); QVBoxLayout *middlevbox = new QVBoxLayout(middlehbox); middlevbox->addSpacing(5); d->layout = middlevbox; // we'll add more items later in addLayout() middlehbox->addSpacing(5); QLabel *middle3 = new QLabel(this); middle3->setFixedWidth(4); middle3->setPaletteBackgroundPixmap(back); middlehbox->addWidget(middle3); // bottom row QHBoxLayout *bottomhbox = new QHBoxLayout(vbox); QLabel *bottom1 = new QLabel(this); bottom1->setFixedSize( 4, 4 ); bottom1->setPaletteBackgroundPixmap(back); bottomhbox->addWidget(bottom1); QLabel *bottom2 = new QLabel(this); bottom2->setFixedHeight(4); bottom2->setPaletteBackgroundPixmap(back); bottomhbox->addWidget(bottom2); QLabel *bottom3 = new QLabel(this); bottom3->setFixedSize( 4, 4 ); bottom3->setPaletteBackgroundPixmap(back); bottomhbox->addWidget(bottom3); } FancyPopup::~FancyPopup() { } void FancyPopup::addLayout(QLayout *layout, int stretch) { d->layout->addLayout(layout, stretch); d->layout->addSpacing(5); } void FancyPopup::show() { if ( size() != sizeHint() ) resize( sizeHint() ); // minimumSizeHint() // position popup move ( d->position() ); // display popup d->hideTimer->start( d->hideTimeout ); QFrame::show(); } void FancyPopup::hideEvent(QHideEvent *e) { d->hideTimer->stop(); deleteLater(); QFrame::hideEvent(e); } void FancyPopup::mouseReleaseEvent(QMouseEvent *e) { QWidget *closeButton = (QWidget *)child("closeButton"); if ( closeButton ) { QPoint p = closeButton->mapFromParent( e->pos() ); if ( p.x() >= 0 && p.y() >= 0 && p.x() < closeButton->width() && p.y() < closeButton->height() ) QFrame::mouseReleaseEvent(e); } emit clicked(); emit clicked((int)e->button()); } void FancyPopup::restartHideTimer() { d->hideTimer->stop(); d->hideTimer->start( d->hideTimeout ); } void FancyPopup::setHideTimeout(int time) { FancyPopup::Private::hideTimeout = time; } void FancyPopup::setBorderColor(QColor c) { FancyPopup::Private::backgroundColor = c; } #include "fancypopup.moc"