00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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 <qregexp.h>
00033 #include <qtextstream.h>
00034 #include <qimage.h>
00035
00036 #include <kaboutdata.h>
00037 #include <kapplication.h>
00038 #include <kconfig.h>
00039 #include <kdebug.h>
00040 #include <kglobal.h>
00041 #include <kiconloader.h>
00042 #include <klocale.h>
00043 #include <kpushbutton.h>
00044 #include <kseparator.h>
00045 #include <kstandarddirs.h>
00046 #include <kstdguiitem.h>
00047 #include <ktextbrowser.h>
00048 #include <kiconeffect.h>
00049 #include <kglobalsettings.h>
00050
00051 #ifdef Q_WS_X11
00052 #include <kwin.h>
00053 #endif
00054
00055 #include "ktip.h"
00056
00057
00058 KTipDatabase::KTipDatabase(const QString &_tipFile)
00059 {
00060 QString tipFile = _tipFile;
00061 if (tipFile.isEmpty())
00062 tipFile = QString::fromLatin1(KGlobal::instance()->aboutData()->appName()) + "/tips";
00063
00064 loadTips(tipFile);
00065
00066 if (!mTips.isEmpty())
00067 mCurrent = kapp->random() % mTips.count();
00068 }
00069
00070
00071 KTipDatabase::KTipDatabase( const QStringList& tipsFiles )
00072 {
00073 if ( tipsFiles.isEmpty() || ( ( tipsFiles.count() == 1 ) && tipsFiles.first().isEmpty() ) )
00074 {
00075 addTips(QString::fromLatin1(KGlobal::instance()->aboutData()->appName()) + "/tips");
00076 }
00077 else
00078 {
00079 for (QStringList::ConstIterator it = tipsFiles.begin(); it != tipsFiles.end(); ++it)
00080 addTips( *it );
00081 }
00082 if (!mTips.isEmpty())
00083 mCurrent = kapp->random() % mTips.count();
00084
00085 }
00086
00087 void KTipDatabase::loadTips(const QString &tipFile)
00088 {
00089 mTips.clear();
00090 addTips(tipFile);
00091 }
00092
00093
00094
00095
00096 void KTipDatabase::addTips(const QString& tipFile )
00097 {
00098 QString fileName = locate("data", tipFile);
00099
00100 if (fileName.isEmpty())
00101 {
00102 kdDebug() << "KTipDatabase::addTips: can't find '" << tipFile << "' in standard dirs" << endl;
00103 return;
00104 }
00105
00106 QFile file(fileName);
00107 if (!file.open(IO_ReadOnly))
00108 {
00109 kdDebug() << "KTipDatabase::addTips: can't open '" << fileName << "' for reading" << endl;
00110 return;
00111 }
00112
00113 QByteArray data = file.readAll();
00114 QString content = QString::fromUtf8(data.data(), data.size());
00115 const QRegExp rx("\\n+");
00116
00117 int pos = -1;
00118 while ((pos = content.find("<html>", pos + 1, false)) != -1)
00119 {
00120
00121
00122 QString tip = content
00123 .mid(pos + 6, content.find("</html>", pos, false) - pos - 6)
00124 .replace(rx, "\n");
00125 if (!tip.endsWith("\n"))
00126 tip += "\n";
00127 if (tip.startsWith("\n"))
00128 tip = tip.mid(1);
00129 if (tip.isEmpty())
00130 {
00131 kdDebug() << "Empty tip found! Skipping! " << pos << endl;
00132 continue;
00133 }
00134 mTips.append(tip);
00135 }
00136
00137 file.close();
00138
00139 }
00140
00141 void KTipDatabase::nextTip()
00142 {
00143 if (mTips.isEmpty())
00144 return ;
00145 mCurrent += 1;
00146 if (mCurrent >= (int) mTips.count())
00147 mCurrent = 0;
00148 }
00149
00150
00151 void KTipDatabase::prevTip()
00152 {
00153 if (mTips.isEmpty())
00154 return ;
00155 mCurrent -= 1;
00156 if (mCurrent < 0)
00157 mCurrent = mTips.count() - 1;
00158 }
00159
00160
00161 QString KTipDatabase::tip() const
00162 {
00163 if (mTips.isEmpty())
00164 return QString::null;
00165 return mTips[mCurrent];
00166 }
00167
00168 KTipDialog *KTipDialog::mInstance = 0;
00169
00170
00171 KTipDialog::KTipDialog(KTipDatabase *db, QWidget *parent, const char *name)
00172 : KDialog(parent, name)
00173 {
00178 bool isTipDialog = (parent);
00179
00180 QImage img;
00181 int h,s,v;
00182
00183 mBlendedColor = KGlobalSettings::activeTitleColor();
00184 mBlendedColor.hsv(&h,&s,&v);
00185 mBlendedColor.setHsv(h, int(s*(71/76.0)), int(v*(67/93.0)));
00186
00187 if (!isTipDialog)
00188 {
00189 img = QImage(locate("data", "kdewizard/pics/wizard_small.png"));
00190
00191 KIconEffect::colorize(img, mBlendedColor, 1.0);
00192 QRgb colPixel( img.pixel(0,0) );
00193
00194 mBlendedColor = QColor(qRed(colPixel),qGreen(colPixel),qBlue(colPixel));
00195 }
00196
00197 mBaseColor = KGlobalSettings::alternateBackgroundColor();
00198 mBaseColor.hsv(&h,&s,&v);
00199 mBaseColor.setHsv(h, int(s*(10/6.0)), int(v*(93/99.0)));
00200
00201 mTextColor = KGlobalSettings::textColor();
00202
00203
00204 mDatabase = db;
00205
00206 setCaption(i18n("Tip of the Day"));
00207 #ifdef Q_WS_X11
00208 KWin::setIcons( winId(),
00209 KGlobal::iconLoader()->loadIcon( "idea", KIcon::NoGroup, 32 ),
00210 KGlobal::iconLoader()->loadIcon( "idea", KIcon::NoGroup, 16 ) );
00211 #endif
00212 QVBoxLayout *vbox = new QVBoxLayout(this, marginHint(), spacingHint());
00213
00214 if (isTipDialog)
00215 {
00216 QHBoxLayout *pl = new QHBoxLayout(vbox, 0, 0);
00217
00218 QLabel *bulb = new QLabel(this);
00219 bulb->setPixmap(locate("data", "kdeui/pics/ktip-bulb.png"));
00220 pl->addWidget(bulb);
00221
00222 QLabel *titlePane = new QLabel(this);
00223 titlePane->setBackgroundPixmap(locate("data", "kdeui/pics/ktip-background.png"));
00224 titlePane->setText(i18n("Did you know...?\n"));
00225 titlePane->setFont(QFont(KGlobalSettings::generalFont().family(), 20, QFont::Bold));
00226 titlePane->setAlignment(QLabel::AlignCenter);
00227 pl->addWidget(titlePane, 100);
00228 }
00229
00230 QHBox *hbox = new QHBox(this);
00231 hbox->setSpacing(0);
00232 hbox->setFrameStyle(QFrame::Panel | QFrame::Sunken);
00233 vbox->addWidget(hbox);
00234
00235 QHBox *tl = new QHBox(hbox);
00236 tl->setMargin(7);
00237 tl->setBackgroundColor(mBlendedColor);
00238
00239 QHBox *topLeft = new QHBox(tl);
00240 topLeft->setMargin(15);
00241 topLeft->setBackgroundColor(mBaseColor);
00242
00243 mTipText = new KTextBrowser(topLeft);
00244
00245 mTipText->setWrapPolicy( QTextEdit::AtWordOrDocumentBoundary );
00246 mTipText->mimeSourceFactory()->addFilePath(
00247 KGlobal::dirs()->findResourceDir("data", "kdewizard/pics")+"kdewizard/pics/");
00248 mTipText->setFrameStyle(QFrame::NoFrame | QFrame::Plain);
00249 mTipText->setHScrollBarMode(QScrollView::AlwaysOff);
00250 mTipText->setLinkUnderline(false);
00251
00252 QStyleSheet *sheet = mTipText->styleSheet();
00253 QStyleSheetItem *item = sheet->item("a");
00254 item->setFontWeight(QFont::Bold);
00255 mTipText->setStyleSheet(sheet);
00256 QPalette pal = mTipText->palette();
00257 pal.setColor( QPalette::Active, QColorGroup::Link, mBlendedColor );
00258 pal.setColor( QPalette::Inactive, QColorGroup::Link, mBlendedColor );
00259 mTipText->setPalette(pal);
00260
00261 QStringList icons = KGlobal::dirs()->resourceDirs("icon");
00262 QStringList::Iterator it;
00263 for (it = icons.begin(); it != icons.end(); ++it)
00264 mTipText->mimeSourceFactory()->addFilePath(*it);
00265
00266 if (!isTipDialog)
00267 {
00268 QLabel *l = new QLabel(hbox);
00269 l->setPixmap(img);
00270 l->setBackgroundColor(mBlendedColor);
00271 l->setAlignment(Qt::AlignRight | Qt::AlignBottom);
00272
00273 resize(550, 230);
00274 QSize sh = size();
00275
00276 QRect rect = KGlobalSettings::splashScreenDesktopGeometry();
00277
00278 move(rect.x() + (rect.width() - sh.width())/2,
00279 rect.y() + (rect.height() - sh.height())/2);
00280 }
00281
00282 KSeparator* sep = new KSeparator( KSeparator::HLine, this);
00283 vbox->addWidget(sep);
00284
00285 QHBoxLayout *hbox2 = new QHBoxLayout(vbox, 4);
00286
00287 mTipOnStart = new QCheckBox(i18n("&Show tips on startup"), this);
00288 hbox2->addWidget(mTipOnStart, 1);
00289
00290 KPushButton *prev = new KPushButton( KStdGuiItem::back(
00291 KStdGuiItem::UseRTL ), this );
00292 prev->setText( i18n("&Previous") );
00293 hbox2->addWidget(prev);
00294
00295 KPushButton *next = new KPushButton( KStdGuiItem::forward(
00296 KStdGuiItem::UseRTL ), this );
00297 next->setText( i18n("Opposite to Previous","&Next") );
00298 hbox2->addWidget(next);
00299
00300 KPushButton *ok = new KPushButton(KStdGuiItem::close(), this);
00301 ok->setDefault(true);
00302 hbox2->addWidget(ok);
00303
00304 KConfigGroup config(kapp->config(), "TipOfDay");
00305 mTipOnStart->setChecked(config.readBoolEntry("RunOnStart", true));
00306
00307 connect(next, SIGNAL(clicked()), this, SLOT(nextTip()));
00308 connect(prev, SIGNAL(clicked()), this, SLOT(prevTip()));
00309 connect(ok, SIGNAL(clicked()), this, SLOT(accept()));
00310 connect(mTipOnStart, SIGNAL(toggled(bool)), this, SLOT(showOnStart(bool)));
00311
00312 ok->setFocus();
00313
00314 nextTip();
00315 }
00316
00317 KTipDialog::~KTipDialog()
00318 {
00319 if( mInstance==this )
00320 mInstance = 0L;
00321 }
00322
00323 void KTipDialog::showTip(const QString &tipFile, bool force)
00324 {
00325 showTip(kapp->mainWidget(), tipFile, force);
00326 }
00327
00328 void KTipDialog::showTip(QWidget *parent, const QString &tipFile, bool force)
00329 {
00330 showMultiTip( parent, QStringList(tipFile), force );
00331 }
00332
00333 void KTipDialog::showMultiTip(QWidget *parent, const QStringList &tipFiles, bool force)
00334 {
00335 KConfigGroup configGroup(kapp->config(), "TipOfDay");
00336
00337 const bool runOnStart = configGroup.readBoolEntry("RunOnStart", true);
00338
00339 if (!force)
00340 {
00341 if (!runOnStart)
00342 return;
00343
00344 bool hasLastShown = configGroup.hasKey("TipLastShown");
00345 if (hasLastShown)
00346 {
00347 const int oneDay = 24*60*60;
00348 QDateTime lastShown = configGroup.readDateTimeEntry("TipLastShown");
00349
00350 if (lastShown.secsTo(QDateTime::currentDateTime()) < (oneDay + (kapp->random() % (10*oneDay))))
00351 return;
00352 }
00353 configGroup.writeEntry("TipLastShown", QDateTime::currentDateTime());
00354 kapp->config()->sync();
00355 if (!hasLastShown)
00356 return;
00357 }
00358
00359 if (!mInstance)
00360 mInstance = new KTipDialog(new KTipDatabase(tipFiles), parent);
00361 else
00362
00363
00364 mInstance->mTipOnStart->setChecked(runOnStart);
00365
00366 mInstance->show();
00367 mInstance->raise();
00368 }
00369
00370 void KTipDialog::prevTip()
00371 {
00372 mDatabase->prevTip();
00373 mTipText->setText(QString::fromLatin1(
00374 "<qt text=\"%1\" bgcolor=\"%2\">%3</qt>")
00375 .arg(mTextColor.name())
00376 .arg(mBaseColor.name())
00377 .arg(i18n(mDatabase->tip().utf8())));
00378 mTipText->setContentsPos(0, 0);
00379 }
00380
00381 void KTipDialog::nextTip()
00382 {
00383 mDatabase->nextTip();
00384 mTipText->setText(QString::fromLatin1("<qt text=\"%1\" bgcolor=\"%2\">%3</qt>")
00385 .arg(mTextColor.name())
00386 .arg(mBaseColor.name())
00387 .arg(i18n(mDatabase->tip().utf8())));
00388 mTipText->setContentsPos(0, 0);
00389 }
00390
00391 void KTipDialog::showOnStart(bool on)
00392 {
00393 setShowOnStart(on);
00394 }
00395
00396 void KTipDialog::setShowOnStart(bool on)
00397 {
00398 KConfigGroup config(kapp->config(), "TipOfDay");
00399 config.writeEntry("RunOnStart", on);
00400 config.sync();
00401 }
00402
00403 bool KTipDialog::eventFilter(QObject *o, QEvent *e)
00404 {
00405 if (o == mTipText && e->type()== QEvent::KeyPress &&
00406 (((QKeyEvent *)e)->key() == Key_Return ||
00407 ((QKeyEvent *)e)->key() == Key_Space ))
00408 accept();
00409
00410
00411
00412
00413
00414
00415
00416 return QWidget::eventFilter( o, e );
00417 }
00418
00419 void KTipDialog::virtual_hook( int id, void* data )
00420 {
00421 KDialog::virtual_hook( id, data );
00422 }
00423
00424 #include "ktip.moc"