kdeui Library API Documentation

ktip.cpp

00001 /*****************************************************************
00002 
00003 Copyright (c) 2000-2003 Matthias Hoelzer-Kluepfel <mhk@kde.org>
00004                         Tobias Koenig <tokoe@kde.org>
00005                         Daniel Molkentin <molkentin@kde.org>
00006 
00007 Permission is hereby granted, free of charge, to any person obtaining a copy
00008 of this software and associated documentation files (the "Software"), to deal
00009 in the Software without restriction, including without limitation the rights
00010 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00011 copies of the Software, and to permit persons to whom the Software is
00012 furnished to do so, subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included in
00015 all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00018 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00020 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023 
00024 ******************************************************************/
00025 
00026 #include <qcheckbox.h>
00027 #include <qfile.h>
00028 #include <qhbox.h>
00029 #include <qlabel.h>
00030 #include <qlayout.h>
00031 #include <qpushbutton.h>
00032 #include <qtextstream.h>
00033 #include <qimage.h>
00034 
00035 #include <kaboutdata.h>
00036 #include <kapplication.h>
00037 #include <kconfig.h>
00038 #include <kdebug.h>
00039 #include <kglobal.h>
00040 #include <kiconloader.h>
00041 #include <klocale.h>
00042 #include <kpushbutton.h>
00043 #include <kseparator.h>
00044 #include <kstandarddirs.h>
00045 #include <kstdguiitem.h>
00046 #include <ktextbrowser.h>
00047 #include <kiconeffect.h>
00048 #include <kglobalsettings.h>
00049 
00050 #include "ktip.h"
00051 
00052 
00053 KTipDatabase::KTipDatabase(const QString &_tipFile)
00054 {
00055     QString tipFile = _tipFile;
00056     if (tipFile.isEmpty())
00057     tipFile = QString::fromLatin1(KGlobal::instance()->aboutData()->appName()) + "/tips";
00058 
00059     loadTips(tipFile);
00060 
00061     if (!mTips.isEmpty())
00062     mCurrent = kapp->random() % mTips.count();
00063 }
00064 
00065 
00066 KTipDatabase::KTipDatabase( const QStringList& tipsFiles )
00067 {
00068    if ( tipsFiles.isEmpty() || ( ( tipsFiles.count() == 1 ) && tipsFiles.first().isEmpty() ) )
00069    {
00070        addTips(QString::fromLatin1(KGlobal::instance()->aboutData()->appName()) + "/tips");
00071    }
00072    else
00073    {
00074        for (QStringList::ConstIterator it = tipsFiles.begin(); it != tipsFiles.end(); ++it)
00075            addTips( *it );
00076    }
00077     if (!mTips.isEmpty())
00078     mCurrent = kapp->random() % mTips.count();
00079 
00080 }
00081 
00082 void KTipDatabase::loadTips(const QString &tipFile)
00083 {
00084     mTips.clear();
00085     addTips(tipFile);
00086 }
00087 
00088 // if you change something here, please update the script
00089 // preparetips, which depends on extracting exactly the same
00090 // text as done here.
00091 void KTipDatabase::addTips(const QString& tipFile )
00092 {
00093     QString fileName = locate("data", tipFile);
00094 
00095     if (fileName.isEmpty())
00096     {
00097     kdDebug() << "KTipDatabase::addTips: can't find '" << tipFile << "' in standard dirs" << endl;
00098         return;
00099     }
00100 
00101     QFile file(fileName);
00102     if (!file.open(IO_ReadOnly))
00103     {
00104     kdDebug() << "KTipDatabase::addTips: can't open '" << fileName << "' for reading" << endl;
00105     return;
00106     }
00107 
00108     QString content = file.readAll();
00109 
00110     int pos = -1;
00111     while ((pos = content.find("<html>", pos + 1, false)) != -1)
00112     {
00113     QString tip = content.mid(pos + 6, content.find("</html>", pos, false) - pos - 6);
00114     if (tip.startsWith("\n"))
00115         tip = tip.mid(1);
00116     mTips.append(tip);
00117     }
00118 
00119     file.close();
00120 
00121 }
00122 
00123 void KTipDatabase::nextTip()
00124 {
00125     if (mTips.isEmpty())
00126     return ;
00127     mCurrent += 1;
00128     if (mCurrent >= (int) mTips.count())
00129     mCurrent = 0;
00130 }
00131 
00132 
00133 void KTipDatabase::prevTip()
00134 {
00135     if (mTips.isEmpty())
00136     return ;
00137     mCurrent -= 1;
00138     if (mCurrent < 0)
00139     mCurrent = mTips.count() - 1;
00140 }
00141 
00142 
00143 QString KTipDatabase::tip() const
00144 {
00145     if (mTips.isEmpty())
00146     return QString::null;
00147     return mTips[mCurrent];
00148 }
00149 
00150 KTipDialog *KTipDialog::mInstance = 0;
00151 
00152 
00153 KTipDialog::KTipDialog(KTipDatabase *db, QWidget *parent, const char *name)
00154   : KDialog(parent, name)
00155 {
00160     bool isTipDialog = (parent != 0);
00161 
00162     QImage img;
00163     int h,s,v;
00164 
00165     mBlendedColor = KGlobalSettings::activeTitleColor();
00166     mBlendedColor.hsv(&h,&s,&v);
00167     mBlendedColor.setHsv(h, int(s*(71/76.0)), int(v*(67/93.0)));
00168 
00169     if (!isTipDialog)
00170     {
00171     img = QImage(locate("data", "kdewizard/pics/wizard_small.png"));
00172     // colorize and check to figure the correct color
00173     KIconEffect::colorize(img, mBlendedColor, 1.0);
00174     QRgb colPixel( img.pixel(0,0) );
00175 
00176     mBlendedColor = QColor(qRed(colPixel),qGreen(colPixel),qBlue(colPixel));
00177     }
00178 
00179     mBaseColor = KGlobalSettings::alternateBackgroundColor();
00180     mBaseColor.hsv(&h,&s,&v);
00181     mBaseColor.setHsv(h, int(s*(10/6.0)), int(v*(93/99.0)));
00182 
00183     mTextColor = KGlobalSettings::textColor();
00184 
00185 
00186     mDatabase = db;
00187 
00188     setCaption(i18n("Tip of the Day"));
00189     setIcon(KGlobal::iconLoader()->loadIcon("ktip", KIcon::Small));
00190 
00191     QVBoxLayout *vbox = new QVBoxLayout(this, marginHint(), spacingHint());
00192 
00193    if (isTipDialog)
00194     {
00195     QHBoxLayout *pl = new QHBoxLayout(vbox, 0, 0);
00196 
00197     QLabel *bulb = new QLabel(this);
00198     bulb->setPixmap(locate("data", "kdeui/pics/ktip-bulb.png"));
00199     pl->addWidget(bulb);
00200 
00201     QLabel *titlePane = new QLabel(this);
00202     titlePane->setBackgroundPixmap(locate("data", "kdeui/pics/ktip-background.png"));
00203     titlePane->setText(i18n("Did you know...?\n"));
00204     titlePane->setFont(QFont(KGlobalSettings::generalFont().family(), 20, QFont::Bold));
00205     titlePane->setAlignment(QLabel::AlignCenter);
00206     pl->addWidget(titlePane, 100);
00207     }
00208 
00209     QHBox *hbox = new QHBox(this);
00210     hbox->setSpacing(0);
00211     hbox->setFrameStyle(QFrame::Panel | QFrame::Sunken);
00212     vbox->addWidget(hbox);
00213 
00214     QHBox *tl = new QHBox(hbox);
00215     tl->setMargin(7);
00216     tl->setBackgroundColor(mBlendedColor);
00217 
00218     QHBox *topLeft = new QHBox(tl);
00219     topLeft->setMargin(15);
00220     topLeft->setBackgroundColor(mBaseColor);
00221 
00222     mTipText = new KTextBrowser(topLeft);
00223 
00224     mTipText->setWrapPolicy( QTextEdit::AtWordOrDocumentBoundary );
00225     mTipText->mimeSourceFactory()->addFilePath(
00226     KGlobal::dirs()->findResourceDir("data", "kdewizard/pics")+"kdewizard/pics/");
00227     mTipText->setFrameStyle(QFrame::NoFrame | QFrame::Plain);
00228     mTipText->setHScrollBarMode(QScrollView::AlwaysOff);
00229     mTipText->setLinkUnderline(false);
00230 
00231     QStyleSheet *sheet = mTipText->styleSheet();
00232     QStyleSheetItem *item = sheet->item("a");
00233     item->setFontWeight(QFont::Bold);
00234     mTipText->setStyleSheet(sheet);
00235     QPalette pal = mTipText->palette();
00236     pal.setColor( QPalette::Active, QColorGroup::Link, mBlendedColor );
00237     pal.setColor( QPalette::Inactive, QColorGroup::Link, mBlendedColor );
00238     mTipText->setPalette(pal);
00239 
00240     QStringList icons = KGlobal::dirs()->resourceDirs("icon");
00241     QStringList::Iterator it;
00242     for (it = icons.begin(); it != icons.end(); ++it)
00243         mTipText->mimeSourceFactory()->addFilePath(*it);
00244 
00245     if (!isTipDialog)
00246     {
00247     QLabel *l = new QLabel(hbox);
00248     l->setPixmap(img);
00249     l->setBackgroundColor(mBlendedColor);
00250     l->setAlignment(Qt::AlignRight | Qt::AlignBottom);
00251 
00252     resize(550, 230);
00253         QSize sh = size();
00254 
00255         QRect rect = KGlobalSettings::splashScreenDesktopGeometry();
00256 
00257         move(rect.x() + (rect.width() - sh.width())/2,
00258     rect.y() + (rect.height() - sh.height())/2);
00259     }
00260 
00261     KSeparator* sep = new KSeparator( KSeparator::HLine, this);
00262     vbox->addWidget(sep);
00263 
00264     QHBoxLayout *hbox2 = new QHBoxLayout(vbox, 4);
00265 
00266     mTipOnStart = new QCheckBox(i18n("&Show tips on startup"), this);
00267     hbox2->addWidget(mTipOnStart, 1);
00268 
00269     KPushButton *prev = new KPushButton( KStdGuiItem::back(
00270             KStdGuiItem::UseRTL ), this );
00271     prev->setText( i18n("&Previous") );
00272     hbox2->addWidget(prev);
00273 
00274     KPushButton *next = new KPushButton( KStdGuiItem::forward(
00275             KStdGuiItem::UseRTL ), this );
00276     next->setText( i18n("&Next") );
00277     hbox2->addWidget(next);
00278 
00279     KPushButton *ok = new KPushButton(KStdGuiItem::close(), this);
00280     ok->setDefault(true);
00281     hbox2->addWidget(ok);
00282 
00283     KConfigGroup config(kapp->config(), "TipOfDay");
00284     mTipOnStart->setChecked(config.readBoolEntry("RunOnStart", false));
00285 
00286     connect(next, SIGNAL(clicked()), this, SLOT(nextTip()));
00287     connect(prev, SIGNAL(clicked()), this, SLOT(prevTip()));
00288     connect(ok, SIGNAL(clicked()), this, SLOT(accept()));
00289     connect(mTipOnStart, SIGNAL(toggled(bool)), this, SLOT(showOnStart(bool)));
00290 
00291     ok->setFocus();
00292 
00293     nextTip();
00294 }
00295 
00296 KTipDialog::~KTipDialog()
00297 {
00298     if( mInstance==this )
00299         mInstance = 0L;
00300 }
00301 
00302 void KTipDialog::showTip(const QString &tipFile, bool force)
00303 {
00304     showTip(kapp->mainWidget(), tipFile, force);
00305 }
00306 
00307 void KTipDialog::showTip(QWidget *parent, const QString &tipFile, bool force)
00308 {
00309   showMultiTip( parent, QStringList(tipFile), force );
00310 }
00311 
00312 void KTipDialog::showMultiTip(QWidget *parent, const QStringList &tipFiles, bool force)
00313 {
00314     KConfigGroup configGroup(kapp->config(), "TipOfDay");
00315 
00316     const bool runOnStart = configGroup.readBoolEntry("RunOnStart", false);
00317 
00318     if (!force)
00319     {
00320         if (!runOnStart)
00321         return;
00322 
00323         bool hasLastShown = configGroup.hasKey("TipLastShown");
00324         if (hasLastShown)
00325         {
00326            const int oneDay = 24*60*60;
00327            QDateTime lastShown = configGroup.readDateTimeEntry("TipLastShown");
00328            // Show tip roughly once a week
00329            if (lastShown.secsTo(QDateTime::currentDateTime()) < (oneDay + (kapp->random() % (10*oneDay))))
00330                return;
00331         }
00332         configGroup.writeEntry("TipLastShown", QDateTime::currentDateTime());
00333         kapp->config()->sync();
00334         if (!hasLastShown)
00335            return; // Don't show tip on first start
00336     }
00337 
00338     if (!mInstance)
00339     mInstance = new KTipDialog(new KTipDatabase(tipFiles), parent);
00340     else
00341     // The application might have changed the RunOnStart option in its own
00342     // configuration dialog, so we should update the checkbox.
00343       mInstance->mTipOnStart->setChecked(runOnStart);
00344 
00345       mInstance->show();
00346       mInstance->raise();
00347   }
00348 
00349   void KTipDialog::prevTip()
00350   {
00351       mDatabase->prevTip();
00352       mTipText->setText(QString::fromLatin1(
00353      "<qt text=\"%1\" bgcolor=\"%2\">%3</qt>")
00354      .arg(mTextColor.name())
00355      .arg(mBaseColor.name())
00356      .arg(i18n(mDatabase->tip().utf8())));
00357   }
00358 
00359   void KTipDialog::nextTip()
00360   {
00361       mDatabase->nextTip();
00362       mTipText->setText(QString::fromLatin1("<qt text=\"%1\" bgcolor=\"%2\">%3</qt>")
00363         .arg(mTextColor.name())
00364         .arg(mBaseColor.name())
00365         .arg(i18n(mDatabase->tip().utf8())));
00366   }
00367 
00368   void KTipDialog::showOnStart(bool on)
00369   {
00370       setShowOnStart(on);
00371   }
00372 
00373   void KTipDialog::setShowOnStart(bool on)
00374   {
00375       KConfigGroup config(kapp->config(), "TipOfDay");
00376       config.writeEntry("RunOnStart", on);
00377       config.sync();
00378   }
00379 
00380   bool KTipDialog::eventFilter(QObject *o, QEvent *e)
00381   {
00382     if (o == mTipText && e->type()== QEvent::KeyPress &&
00383         (((QKeyEvent *)e)->key() == Key_Return ||
00384         ((QKeyEvent *)e)->key() == Key_Space ))
00385         accept();
00386 
00387     // If the user presses Return or Space, we close the dialog as if the
00388     // default button was pressed even if the KTextBrowser has the keyboard
00389     // focus. This could have the bad side-effect that the user cannot use the
00390     // keyboard to open urls in the KTextBrowser, so we just let it handle
00391     // the key event _additionally_. (Antonio)
00392 
00393     return QWidget::eventFilter( o, e );
00394 }
00395 
00396 void KTipDialog::virtual_hook( int id, void* data )
00397 {
00398     KDialog::virtual_hook( id, data );
00399 }
00400 
00401 #include "ktip.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.3.90.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 30 10:12:02 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003