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 
00148     return mTips[mCurrent];
00149 }
00150 
00151 KTipDialog *KTipDialog::mInstance = 0;
00152 
00153 
00154 KTipDialog::KTipDialog(KTipDatabase *db, QWidget *parent, const char *name)
00155   : KDialog(parent, name)
00156 {
00161     bool isTipDialog = (parent != 0);
00162 
00163     QImage img;
00164     int h,s,v;
00165 
00166     mBlendedColor = KGlobalSettings::activeTitleColor();
00167     mBlendedColor.hsv(&h,&s,&v);
00168     mBlendedColor.setHsv(h, int(s*(71/76.0)), int(v*(67/93.0)));
00169 
00170     if (!isTipDialog)
00171     {
00172     img = QImage(locate("data", "kdewizard/pics/wizard_small.png"));
00173     // colorize and check to figure the correct color
00174     KIconEffect::colorize(img, mBlendedColor, 1.0);
00175     QRgb colPixel( img.pixel(0,0) );
00176 
00177     mBlendedColor = QColor(qRed(colPixel),qGreen(colPixel),qBlue(colPixel));
00178     }
00179 
00180     mBaseColor = KGlobalSettings::alternateBackgroundColor();
00181     mBaseColor.hsv(&h,&s,&v);
00182     mBaseColor.setHsv(h, int(s*(10/6.0)), int(v*(93/99.0)));
00183 
00184     mTextColor = KGlobalSettings::textColor();
00185 
00186 
00187     mDatabase = db;
00188 
00189     setCaption(i18n("Tip of the Day"));
00190     setIcon(KGlobal::iconLoader()->loadIcon("ktip", KIcon::Small));
00191 
00192     QVBoxLayout *vbox = new QVBoxLayout(this, marginHint(), spacingHint());
00193 
00194    if (isTipDialog)
00195     {
00196     QHBoxLayout *pl = new QHBoxLayout(vbox, 0, 0);
00197 
00198     QLabel *bulb = new QLabel(this);
00199     bulb->setPixmap(locate("data", "kdeui/pics/ktip-bulb.png"));
00200     pl->addWidget(bulb);
00201 
00202     QLabel *titlePane = new QLabel(this);
00203     titlePane->setBackgroundPixmap(locate("data", "kdeui/pics/ktip-background.png"));
00204     titlePane->setText(i18n("Did you know...?\n"));
00205     titlePane->setFont(QFont(KGlobalSettings::generalFont().family(), 20, QFont::Bold));
00206     titlePane->setAlignment(QLabel::AlignCenter);
00207     pl->addWidget(titlePane, 100);
00208     }
00209 
00210     QHBox *hbox = new QHBox(this);
00211     hbox->setSpacing(0);
00212     hbox->setFrameStyle(QFrame::Panel | QFrame::Sunken);
00213     vbox->addWidget(hbox);
00214 
00215     QHBox *tl = new QHBox(hbox);
00216     tl->setMargin(7);
00217     tl->setBackgroundColor(mBlendedColor);
00218 
00219     QHBox *topLeft = new QHBox(tl);
00220     topLeft->setMargin(15);
00221     topLeft->setBackgroundColor(mBaseColor);
00222 
00223     mTipText = new KTextBrowser(topLeft);
00224 
00225     mTipText->setWrapPolicy( QTextEdit::AtWordOrDocumentBoundary );
00226     mTipText->mimeSourceFactory()->addFilePath(
00227     KGlobal::dirs()->findResourceDir("data", "kdewizard/pics")+"kdewizard/pics/");
00228     mTipText->setFrameStyle(QFrame::NoFrame | QFrame::Plain);
00229     mTipText->setHScrollBarMode(QScrollView::AlwaysOff);
00230     mTipText->setLinkUnderline(false);
00231 
00232     QStyleSheet *sheet = mTipText->styleSheet();
00233     QStyleSheetItem *item = sheet->item("a");
00234     item->setFontWeight(QFont::Bold);
00235     mTipText->setStyleSheet(sheet);
00236     QPalette pal = mTipText->palette();
00237     pal.setColor( QPalette::Active, QColorGroup::Link, mBlendedColor );
00238     pal.setColor( QPalette::Inactive, QColorGroup::Link, mBlendedColor );
00239     mTipText->setPalette(pal);
00240 
00241     QStringList icons = KGlobal::dirs()->resourceDirs("icon");
00242     QStringList::Iterator it;
00243     for (it = icons.begin(); it != icons.end(); ++it)
00244         mTipText->mimeSourceFactory()->addFilePath(*it);
00245 
00246     if (!isTipDialog)
00247     {
00248     QLabel *l = new QLabel(hbox);
00249     l->setPixmap(img);
00250     l->setBackgroundColor(mBlendedColor);
00251     l->setAlignment(Qt::AlignRight | Qt::AlignBottom);
00252 
00253     resize(550, 230);
00254         QSize sh = size();
00255 
00256         QRect rect = KGlobalSettings::splashScreenDesktopGeometry();
00257 
00258         move(rect.x() + (rect.width() - sh.width())/2,
00259     rect.y() + (rect.height() - sh.height())/2);
00260     }
00261 
00262     KSeparator* sep = new KSeparator( KSeparator::HLine, this);
00263     vbox->addWidget(sep);
00264 
00265     QHBoxLayout *hbox2 = new QHBoxLayout(vbox, 4);
00266 
00267     mTipOnStart = new QCheckBox(i18n("&Show tips on startup"), this);
00268     hbox2->addWidget(mTipOnStart, 1);
00269 
00270     KPushButton *prev = new KPushButton( KStdGuiItem::back(
00271             KStdGuiItem::UseRTL ), this );
00272     prev->setText( i18n("&Previous") );
00273     hbox2->addWidget(prev);
00274 
00275     KPushButton *next = new KPushButton( KStdGuiItem::forward(
00276             KStdGuiItem::UseRTL ), this );
00277     next->setText( i18n("&Next") );
00278     hbox2->addWidget(next);
00279 
00280     KPushButton *ok = new KPushButton(KStdGuiItem::close(), this);
00281     ok->setDefault(true);
00282     hbox2->addWidget(ok);
00283 
00284     KConfigGroup config(kapp->config(), "TipOfDay");
00285     mTipOnStart->setChecked(config.readBoolEntry("RunOnStart", true));
00286 
00287     connect(next, SIGNAL(clicked()), this, SLOT(nextTip()));
00288     connect(prev, SIGNAL(clicked()), this, SLOT(prevTip()));
00289     connect(ok, SIGNAL(clicked()), this, SLOT(accept()));
00290     connect(mTipOnStart, SIGNAL(toggled(bool)), this, SLOT(showOnStart(bool)));
00291 
00292     ok->setFocus();
00293 
00294     nextTip();
00295 }
00296 
00297 KTipDialog::~KTipDialog()
00298 {
00299     if( mInstance==this )
00300         mInstance = 0L;
00301 }
00302 
00303 void KTipDialog::showTip(const QString &tipFile, bool force)
00304 {
00305     showTip(kapp->mainWidget(), tipFile, force);
00306 }
00307 
00308 void KTipDialog::showTip(QWidget *parent, const QString &tipFile, bool force)
00309 {
00310   showMultiTip( parent, QStringList(tipFile), force );
00311 }
00312 
00313 void KTipDialog::showMultiTip(QWidget *parent, const QStringList &tipFiles, bool force)
00314 {
00315     KConfigGroup configGroup(kapp->config(), "TipOfDay");
00316 
00317     const bool runOnStart = configGroup.readBoolEntry("RunOnStart", true);
00318 
00319     if (!force)
00320     {
00321         if (!runOnStart)
00322         return;
00323 
00324         bool hasLastShown = configGroup.hasKey("TipLastShown");
00325         if (hasLastShown)
00326         {
00327            const int oneDay = 24*60*60;
00328            QDateTime lastShown = configGroup.readDateTimeEntry("TipLastShown");
00329            // Show tip roughly once a week
00330            if (lastShown.secsTo(QDateTime::currentDateTime()) < (oneDay + (kapp->random() % (10*oneDay))))
00331                return;
00332         }
00333         configGroup.writeEntry("TipLastShown", QDateTime::currentDateTime());
00334         kapp->config()->sync();
00335         if (!hasLastShown)
00336            return; // Don't show tip on first start
00337     }
00338 
00339     if (!mInstance)
00340     mInstance = new KTipDialog(new KTipDatabase(tipFiles), parent);
00341     else
00342     // The application might have changed the RunOnStart option in its own
00343     // configuration dialog, so we should update the checkbox.
00344       mInstance->mTipOnStart->setChecked(runOnStart);
00345 
00346       mInstance->show();
00347       mInstance->raise();
00348   }
00349 
00350   void KTipDialog::prevTip()
00351   {
00352       mDatabase->prevTip();
00353       mTipText->setText(QString::fromLatin1(
00354      "<qt text=\"%1\" bgcolor=\"%2\">%3</qt>")
00355      .arg(mTextColor.name())
00356      .arg(mBaseColor.name())
00357      .arg(i18n(mDatabase->tip().utf8())));
00358   }
00359 
00360   void KTipDialog::nextTip()
00361   {
00362       mDatabase->nextTip();
00363       mTipText->setText(QString::fromLatin1("<qt text=\"%1\" bgcolor=\"%2\">%3</qt>")
00364         .arg(mTextColor.name())
00365         .arg(mBaseColor.name())
00366         .arg(i18n(mDatabase->tip().utf8())));
00367   }
00368 
00369   void KTipDialog::showOnStart(bool on)
00370   {
00371       setShowOnStart(on);
00372   }
00373 
00374   void KTipDialog::setShowOnStart(bool on)
00375   {
00376       KConfigGroup config(kapp->config(), "TipOfDay");
00377       config.writeEntry("RunOnStart", on);
00378       config.sync();
00379   }
00380 
00381   bool KTipDialog::eventFilter(QObject *o, QEvent *e)
00382   {
00383     if (o == mTipText && e->type()== QEvent::KeyPress &&
00384         (((QKeyEvent *)e)->key() == Key_Return ||
00385         ((QKeyEvent *)e)->key() == Key_Space ))
00386         accept();
00387 
00388     // If the user presses Return or Space, we close the dialog as if the
00389     // default button was pressed even if the KTextBrowser has the keyboard
00390     // focus. This could have the bad side-effect that the user cannot use the
00391     // keyboard to open urls in the KTextBrowser, so we just let it handle
00392     // the key event _additionally_. (Antonio)
00393 
00394     return QWidget::eventFilter( o, e );
00395 }
00396 
00397 void KTipDialog::virtual_hook( int id, void* data )
00398 {
00399     KDialog::virtual_hook( id, data );
00400 }
00401 
00402 #include "ktip.moc"
KDE Logo
This file is part of the documentation for kdeui Library Version 3.3.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jan 22 16:45:19 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003