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