Qt logo

Progress Bar and Dialog Example


This example displays either a simple (text-only) or a custom-labelled (user-supplied widget) progress dialog. It also demonstrates simple use of menus.
Implementation:
/****************************************************************************
** $Id: progress.cpp,v 1.2 1999/06/03 01:45:07 warwick Exp $
**
** Copyright (C) 1992-1999 Troll Tech AS.  All rights reserved.
**
** This file is part of an example program for Qt.  This example
** program may be used, distributed and modified without limitation.
**
*****************************************************************************/

#include <qprogressdialog.h>
#include <qapplication.h>
#include <qmenubar.h>
#include <qpopupmenu.h>
#include <qpainter.h>
#include <stdlib.h>

class AnimatedThingy : public QLabel {
public:
    AnimatedThingy( QWidget* parent, const QString& s ) :
        QLabel(parent),
        label(s),
        step(0)
    {
        label+="\n... and wasting CPU\nwith this animation!\n";

        for (int i=0; i<nqix; i++)
            ox[0][i] = oy[0][i] = ox[1][i] = oy[1][i] = 0;
        x0 = y0 = x1 = y1 = 0;
        dx0 = rand()%8+2;
        dy0 = rand()%8+2;
        dx1 = rand()%8+2;
        dy1 = rand()%8+2;
    }

    void show()
    {
        if (!isVisible()) startTimer(100);
        QWidget::show();
    }

    void hide()
    {
        QWidget::hide();
        killTimers();
    }

    QSize sizeHint() const
    {
        return QSize(120,100);
    }

protected:
    void timerEvent(QTimerEvent*)
    {
        QPainter p(this);
        QPen pn=p.pen();
        pn.setWidth(2);
        pn.setColor(backgroundColor());
        p.setPen(pn);

        step = (step + 1) % nqix;

        p.drawLine(ox[0][step], oy[0][step], ox[1][step], oy[1][step]);

        inc(x0, dx0, width());
        inc(y0, dy0, height());
        inc(x1, dx1, width());
        inc(y1, dy1, height());
        ox[0][step] = x0;
        oy[0][step] = y0;
        ox[1][step] = x1;
        oy[1][step] = y1;

        QColor c;
        c.setHsv( (step*255)/nqix, 255, 255 ); // rainbow effect
        pn.setColor(c);
        p.setPen(pn);
        p.drawLine(ox[0][step], oy[0][step], ox[1][step], oy[1][step]);
        p.setPen(colorGroup().text());
        p.drawText(rect(), AlignCenter, label);
    }

    void paintEvent(QPaintEvent* event)
    {
        QPainter p(this);
        QPen pn=p.pen();
        pn.setWidth(2);
        p.setPen(pn);
        p.setClipRect(event->rect());
        for (int i=0; i<nqix; i++) {
            QColor c;
            c.setHsv( (i*255)/nqix, 255, 255 ); // rainbow effect
            pn.setColor(c);
            p.setPen(pn);
            p.drawLine(ox[0][i], oy[0][i], ox[1][i], oy[1][i]);
        }
        p.setPen(colorGroup().text());
        p.drawText(rect(), AlignCenter, label);
    }

private:
    void inc(int& x, int& dx, int b)
    {
        x+=dx;
        if (x<0) { x=0; dx=rand()%8+2; }
        else if (x>=b) { x=b-1; dx=-(rand()%8+2); }
    }

    enum {nqix=10};
    int ox[2][nqix];
    int oy[2][nqix];
    int x0,y0,x1,y1;
    int dx0,dy0,dx1,dy1;
    QString label;
    int step;
};

class CPUWaster : public QWidget
{
    Q_OBJECT

    enum { first_draw_item = 1000, last_draw_item = 1006 };

    int drawItemRects(int id)
    {
        int n = id - first_draw_item;
        int r = 100;
        while (n--) r*=(n%3 ? 5 : 4);
        return r;
    }
    QString drawItemText(int id)
    {
        QString str;
        str.sprintf("%d Rectangles", drawItemRects(id));
        return str;
    }

public:
    CPUWaster() :
        pb(0)
    {
        menubar = new QMenuBar( this, "menu" );
        CHECK_PTR( menubar );

        QPopupMenu* file = new QPopupMenu();
        CHECK_PTR( file );
        menubar->insertItem( "&File", file );
        for (int i=first_draw_item; i<=last_draw_item; i++)
            file->insertItem( drawItemText(i), i );
        connect( menubar, SIGNAL(activated(int)), this, SLOT(doMenuItem(int)) );
        file->insertSeparator();
        file->insertItem( "Quit", qApp,  SLOT(quit()) );

        options = new QPopupMenu();
        CHECK_PTR( options );
        menubar->insertItem( "&Options", options );
        td_id = options->insertItem( "Timer driven", this, SLOT(timerDriven()) );
        ld_id = options->insertItem( "Loop driven", this, SLOT(loopDriven()) );
        options->insertSeparator();
        dl_id = options->insertItem( "Default label", this, SLOT(defaultLabel()) );
        cl_id = options->insertItem( "Custom label", this, SLOT(customLabel()) );
        options->insertSeparator();
        md_id = options->insertItem( "No minimum duration", this, SLOT(toggleMinimumDuration()) );
        options->setCheckable( TRUE );
        loopDriven();
        defaultLabel();

        setFixedSize( 400, 300 );

        setBackgroundColor( black );
    }

public slots:
    void doMenuItem(int id)
    {
        if (id >= first_draw_item && id <= last_draw_item)
            draw(drawItemRects(id));
    }

    void stopDrawing() { got_stop = TRUE; }

    void timerDriven()
    {
        timer_driven = TRUE;
        options->setItemChecked( td_id, TRUE );
        options->setItemChecked( ld_id, FALSE );
    }

    void loopDriven()
    {
        timer_driven = FALSE;
        options->setItemChecked( ld_id, TRUE );
        options->setItemChecked( td_id, FALSE );
    }

    void defaultLabel()
    {
        default_label = TRUE;
        options->setItemChecked( dl_id, TRUE );
        options->setItemChecked( cl_id, FALSE );
    }

    void customLabel()
    {
        default_label = FALSE;
        options->setItemChecked( dl_id, FALSE );
        options->setItemChecked( cl_id, TRUE );
    }

    void toggleMinimumDuration()
    {
        options->setItemChecked( md_id, 
           !options->isItemChecked( md_id ) );
    }

private:
    void timerEvent( QTimerEvent* )
    {
        pb->setProgress( pb->totalSteps() - rects );
        rects--;

        {
            QPainter p(this);

            int ww = width();
            int wh = height();

            if ( ww > 8 && wh > 8 ) {
                QColor c(rand()%255, rand()%255, rand()%255);
                int x = rand() % (ww-8);
                int y = rand() % (wh-8);
                int w = rand() % (ww-x);
                int h = rand() % (wh-y);
                p.fillRect( x, y, w, h, c );
            }
        }

        if (!rects || got_stop) {
            pb->setProgress( pb->totalSteps() );
            QPainter p(this);
            p.fillRect(0, 0, width(), height(), backgroundColor());
            enableDrawingItems(TRUE);
            killTimers();
            delete pb;
            pb = 0;
        }
    }

    QProgressDialog* newProgressDialog( const char* label, int steps, bool modal )
    {
        QProgressDialog *d = new QProgressDialog(label, "Cancel", steps, this,
                                                 "progress", modal);
        if ( options->isItemChecked( md_id ) )
            d->setMinimumDuration(0);
        if ( !default_label )
            d->setLabel( new AnimatedThingy(d,label) );
        return d;
    }

    void enableDrawingItems(bool yes)
    {
        for (int i=first_draw_item; i<=last_draw_item; i++) {
            menubar->setItemEnabled(i, yes);
        }
    }

    void draw(int n)
    {
        if ( timer_driven ) {
            if ( pb ) {
                qWarning("This cannot happen!");
                return;
            }
            rects = n;
            pb = newProgressDialog("Drawing rectangles.\n"
                                   "Using timer event.", n, FALSE);
            pb->setCaption("Please Wait");
            connect(pb, SIGNAL(cancelled()), this, SLOT(stopDrawing()));
            enableDrawingItems(FALSE);
            startTimer(0);
            got_stop = FALSE;
        } else {
            QProgressDialog* lpb = newProgressDialog(
                        "Drawing rectangles.\nUsing loop.", n, TRUE);
            lpb->setCaption("Please Wait");

            QPainter p(this);
            for (int i=0; i<n; i++) {
                lpb->setProgress(i);
                if ( lpb->wasCancelled() )
                    break;

                QColor c(rand()%255, rand()%255, rand()%255);
                int x = rand()%(width()-8);
                int y = rand()%(height()-8);
                int w = rand()%(width()-x);
                int h = rand()%(height()-y);
                p.fillRect(x,y,w,h,c);
            }

            lpb->setProgress(n);

            p.fillRect(0, 0, width(), height(), backgroundColor());
        }
    }

    QMenuBar* menubar;
    QProgressDialog* pb;
    QPopupMenu* options;
    int td_id, ld_id;
    int dl_id, cl_id;
    int md_id;
    int rects;
    bool timer_driven;
    bool default_label;
    bool got_stop;
};

int main( int argc, char **argv )
{
    QApplication a( argc, argv );

    int wincount = argc > 1 ? atoi(argv[1]) : 1;

    for ( int i=0; i<wincount; i++ ) {
        CPUWaster* cpuw = new CPUWaster;
        if ( i == 0 ) a.setMainWidget(cpuw);
        cpuw->show();
    }
    return a.exec();
}

#include "progress.moc"


Copyright 1999 Troll TechTrademarks
Qt version 2.0.2