kpilot Library API Documentation

conduitConfigDialog.cc

00001 /* conduitConfigDialog.cc                KPilot
00002 **
00003 ** Copyright (C) 2001 by Dan Pilone
00004 **
00005 ** This file defines a .ui-based configuration dialog for conduits.
00006 */
00007 
00008 /*
00009 ** This program is free software; you can redistribute it and/or modify
00010 ** it under the terms of the GNU General Public License as published by
00011 ** the Free Software Foundation; either version 2 of the License, or
00012 ** (at your option) any later version.
00013 **
00014 ** This program is distributed in the hope that it will be useful,
00015 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00017 ** GNU General Public License for more details.
00018 **
00019 ** You should have received a copy of the GNU General Public License
00020 ** along with this program in a file called COPYING; if not, write to
00021 ** the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
00022 ** MA 02111-1307, USA.
00023 */
00024 
00025 /*
00026 ** Bug reports and questions can be sent to kde-pim@kde.org
00027 */
00028 
00029 static const char *conduitconfigdialog_id =
00030     "$Id: conduitConfigDialog.cc,v 1.30 2003/11/22 12:20:12 kainhofe Exp $";
00031 
00032 #include "options.h"
00033 
00034 #include <qlistview.h>
00035 #include <qlabel.h>
00036 #include <qtooltip.h>
00037 #include <qfile.h>
00038 #include <qpushbutton.h>
00039 #include <qhbox.h>
00040 #include <qlayout.h>
00041 #include <qwidgetstack.h>
00042 #include <qvbox.h>
00043 
00044 #include <kservice.h>
00045 #include <kservicetype.h>
00046 #include <kuserprofile.h>
00047 #include <kprocess.h>
00048 #include <kmessagebox.h>
00049 #include <kglobal.h>
00050 #include <kstandarddirs.h>
00051 #include <klibloader.h>
00052 #include <kseparator.h>
00053 
00054 #include "plugin.h"
00055 #include "kpilotConfig.h"
00056 
00057 #include "conduitConfigDialog.moc"
00058 
00059 #define CONDUIT_NAME    (0)
00060 #define CONDUIT_COMMENT (1)
00061 #define CONDUIT_DESKTOP (2)
00062 #define CONDUIT_LIBRARY (3)
00063 
00064 class ConduitTip : public QToolTip
00065 {
00066 public:
00067     ConduitTip(QListView *parent);
00068     virtual ~ConduitTip();
00069 
00070 protected:
00071     virtual void maybeTip(const QPoint &);
00072 
00073     QListView *fListView;
00074 } ;
00075 
00076 
00077 ConduitTip::ConduitTip(QListView *p) :
00078     QToolTip(p->viewport(),0L),
00079     fListView(p)
00080 {
00081     FUNCTIONSETUP;
00082 }
00083 
00084 ConduitTip::~ConduitTip()
00085 {
00086     FUNCTIONSETUP;
00087 }
00088 
00089 /* virtual */ void ConduitTip::maybeTip(const QPoint &p)
00090 {
00091     FUNCTIONSETUP;
00092 
00093     QListViewItem *l = fListView->itemAt(p);
00094 
00095     if (!l) return;
00096 
00097     // ConduitListItem *q = static_cast<ConduitListItem *>(l);
00098 
00099 #ifdef DEBUG
00100     DEBUGKPILOT << fname
00101         << ": Tip over "
00102         << l->text(CONDUIT_NAME)
00103         << " with text "
00104         << l->text(CONDUIT_COMMENT)
00105         << endl;
00106 #endif
00107 
00108     QString s = l->text(CONDUIT_COMMENT);
00109 
00110     if (s.isEmpty()) return;
00111     if (s.find(CSL1("<qt>"),0,false) == -1)
00112     {
00113         s.prepend(CSL1("<qt>"));
00114         s.append(CSL1("</qt>"));
00115     }
00116 
00117     tip(fListView->itemRect(l),s);
00118 }
00119 
00120 // Page numbers in the widget stack
00121 #define INTRO            (0)
00122 #define OLD_CONDUIT      (1)
00123 #define BROKEN_CONDUIT   (2)
00124 #define INTERNAL_CONDUIT (3)
00125 #define NEW_CONDUIT      (4)
00126 
00127 
00128 ConduitConfigWidgetBase::ConduitConfigWidgetBase(QHBox *p,const char *n) :
00129     QObject(p,n)
00130 {
00131     p->setSpacing(10);
00132 
00133     QWidget *w = 0L; // For spacing purposes only.
00134     QLabel *l = 0L;
00135     QVBox *v = 0L;
00136 
00137     // Create the left hand column
00138     v = new QVBox(p);
00139     fConduitList = new QListView(v,"ConduitList");
00140     fConduitList->addColumn(i18n("Conduit"));
00141     v->setStretchFactor(fConduitList,0);
00142     v->setSpacing(50);
00143     l = new QLabel(v);    // Just a placekeeper, to fix redraw problems.
00144     l->resize(30,30);
00145     v->setStretchFactor(l,100);
00146 
00147     // Right hand column
00148     fStack = new QWidgetStack(p,"RightPart");
00149 
00150     // Zero'th page in stack
00151     l = new QLabel(fStack);
00152     l->setFrameShape(QLabel::Box);
00153     l->setText(i18n("<qt>Select a conduit in the list to configure it. "
00154         "Checked conduits will be run during a HotSync.</qt>"));
00155     l->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter | Qt::ExpandTabs | Qt::WordBreak);
00156     fStack->addWidget(l,INTRO);
00157 
00158     // First page in stack (right hand column)
00159     l = new QLabel(fStack);
00160     l->setFrameShape(QLabel::Box);
00161     l->setText(i18n("<qt>This conduit appears to be broken and cannot "
00162         "be configured.</qt>"));
00163     l->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter | Qt::ExpandTabs | Qt::WordBreak);
00164     fStack->addWidget(l,BROKEN_CONDUIT);
00165 
00166     // Second page, now with layout in a single column
00167     v = new QVBox(fStack,"OldStyle");
00168     w = new QWidget(v);
00169     v->setStretchFactor(w,50);
00170     fOldStyleLabel = new QLabel(v);
00171     // Within this column, center the button box
00172     QHBox *h = new QHBox(v,"ButtonBox");
00173     w = new QWidget(h);
00174     h->setStretchFactor(w,50);
00175     fConfigureButton = new QPushButton(h);
00176     fConfigureButton->setText(i18n("Configure..."));
00177     w = new QWidget(h);
00178     h->setStretchFactor(w,50);
00179     // Add stretch beneath the button box
00180     w = new QWidget(v);
00181     v->setStretchFactor(w,50);
00182     fStack->addWidget(v,OLD_CONDUIT);
00183 
00184     // Page 3
00185     l = new QLabel(fStack);
00186     l->setFrameShape(QLabel::Box);
00187     l->setText(i18n("<qt>This is an internal conduit which has no "
00188         "configuration options.</qt>"));
00189     l->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter | Qt::ExpandTabs | Qt::WordBreak);
00190     fStack->addWidget(l,INTERNAL_CONDUIT);
00191 }
00192 
00193 
00194 ConduitConfigDialog::ConduitConfigDialog(QWidget * _w, const char *n,
00195     bool m) : UIDialog(_w, n, Ok|Apply|Cancel,m)
00196 {
00197     FUNCTIONSETUP;
00198 
00199     enableButtonSeparator(true);
00200     // selected(0L);
00201 
00202     QHBox *h = dynamic_cast<QHBox *>(widget());
00203     if (!h)
00204     {
00205         h = new QHBox(widget());
00206     }
00207 
00208     fConfigWidget = new ConduitConfigWidget(h,0L);
00209 
00210     QObject::connect(fConfigWidget,SIGNAL(sizeChanged()),
00211         h,SLOT(adjustSize()));
00212     QObject::connect(fConfigWidget,SIGNAL(sizeChanged()),
00213         this,SLOT(adjustSize()));
00214 
00215     (void) conduitconfigdialog_id;
00216 }
00217 
00218 ConduitConfigDialog::~ConduitConfigDialog()
00219 {
00220     FUNCTIONSETUP;
00221 }
00222 
00223 /* virtual */ bool ConduitConfigDialog::validate()
00224 {
00225     return fConfigWidget->release();
00226 }
00227 
00228 /* virtual */ void ConduitConfigDialog::commitChanges()
00229 {
00230     fConfigWidget->commitChanges();
00231 }
00232 
00233 /* virtual */ void ConduitConfigDialog::slotApply()
00234 {
00235     commitChanges();
00236 }
00237 
00238 #define PAGE_SIZE   QSize(440,300)
00239 
00240 ConduitConfigWidget::ConduitConfigWidget(QHBox *p, const char *n,
00241     bool) :
00242     ConduitConfigWidgetBase(p,n),
00243     fConfigure(0L),
00244     fCurrentConduit(0L),
00245     fCurrentConfig(0L),
00246     fCurrentOldStyle(0L),
00247     fParentWidget(p)
00248 {
00249     FUNCTIONSETUP;
00250 
00251     // fConduitList->removeColumn(CONDUIT_COMMENT);
00252     fillLists();
00253     fConduitList->adjustSize();
00254     fConduitList->show();
00255 
00256     fStack->resize(PAGE_SIZE);
00257     fStack->setMinimumSize(PAGE_SIZE);
00258 
00259     QObject::connect(fConduitList,
00260         SIGNAL(selectionChanged(QListViewItem *)),
00261         this,SLOT(selected(QListViewItem *)));
00262     QObject::connect(fConfigureButton,
00263         SIGNAL(clicked()),
00264         this,SLOT(configure()));
00265 
00266     selected(0L);
00267     // adjustSize();
00268     fStack->raiseWidget(INTRO);
00269 
00270     (void) new ConduitTip(fConduitList);
00271 }
00272 
00273 ConduitConfigWidget::~ConduitConfigWidget()
00274 {
00275     FUNCTIONSETUP;
00276     release();
00277 }
00278 
00279 void ConduitConfigWidget::fillLists()
00280 {
00281     FUNCTIONSETUP;
00282 
00283     QStringList potentiallyInstalled =
00284         KPilotConfig::getConfig().setConduitGroup().
00285         getInstalledConduits();
00286     KServiceTypeProfile::OfferList offers =
00287         KServiceTypeProfile::offers(CSL1("KPilotConduit"));
00288 
00289     QValueListIterator < KServiceOffer > availList(offers.begin());
00290     while (availList != offers.end())
00291     {
00292         KSharedPtr < KService > o = (*availList).service();
00293 
00294 #ifdef DEBUG
00295         DEBUGKPILOT << fname << ": "
00296             << o->desktopEntryName()
00297             << " = " << o->name() << endl;
00298 #endif
00299 
00300         QCheckListItem *p = 0L;
00301 
00302         if (!o->exec().isEmpty())
00303         {
00304             kdWarning() << k_funcinfo
00305                 << ": Old-style conduit found "
00306                 << o->name()
00307                 << endl;
00308         }
00309 
00310         p = new QCheckListItem(fConduitList,
00311             o->name(),
00312             QCheckListItem::CheckBox);
00313         p->setMultiLinesEnabled(true);
00314         p->setText(CONDUIT_COMMENT,o->comment());
00315         p->setText(CONDUIT_DESKTOP,o->desktopEntryName());
00316         p->setText(CONDUIT_LIBRARY,o->library());
00317 
00318         if (potentiallyInstalled.findIndex(o->desktopEntryName()) < 0)
00319         {
00320             p->setOn(false);
00321         }
00322         else
00323         {
00324             p->setOn(true);
00325         }
00326 
00327         ++availList;
00328     }
00329 
00330     // Now the (statically compiled) internal conduits
00331     QCheckListItem *p = 0L;
00332 #define IC(a,b,c) p = new QCheckListItem(fConduitList,i18n(a),QCheckListItem::CheckBox); \
00333     p->setText(CONDUIT_COMMENT,i18n(c)); \
00334     p->setText(CONDUIT_LIBRARY,"internal_" b); \
00335     p->setText(CONDUIT_DESKTOP,"internal_" b); \
00336     if (potentiallyInstalled.findIndex(p->text(CONDUIT_DESKTOP))>=0) \
00337         p->setOn(true);
00338 
00339     IC("Kroupware","kroupware",
00340         "Sync the handheld with a Kroupware client (for example, KMail).");
00341     IC("Install Files","fileinstall",
00342         "Install files that are dragged to KPilot onto the handheld.");
00343 
00344 #undef IC
00345 }
00346 
00347 void ConduitConfigWidget::loadAndConfigure(QListViewItem *p) // ,bool exec)
00348 {
00349     FUNCTIONSETUP;
00350 
00351     if (!p)
00352     {
00353 #ifdef DEBUG
00354         DEBUGKPILOT << fname
00355             << ": Executed NULL conduit?"
00356             << endl;
00357 #endif
00358         fStack->raiseWidget(INTRO);
00359         return;
00360     }
00361 
00362 #ifdef DEBUG
00363     DEBUGKPILOT << fname
00364         << ": Executing conduit "
00365         << p->text(CONDUIT_NAME)
00366         << endl;
00367 #endif
00368 
00369     if (p->text(CONDUIT_LIBRARY).isEmpty())
00370     {
00371         fStack->raiseWidget(BROKEN_CONDUIT);
00372         warnNoExec(p);
00373         return;
00374     }
00375 
00376     if (p->text(CONDUIT_LIBRARY).startsWith(CSL1("internal_")))
00377     {
00378         fStack->raiseWidget(INTERNAL_CONDUIT);
00379         return;
00380     }
00381 
00382     QCString library = QFile::encodeName(p->text(CONDUIT_LIBRARY));
00383 
00384     KLibFactory *f = KLibLoader::self()->
00385         factory(library);
00386     if (!f)
00387     {
00388 #ifdef DEBUG
00389         DEBUGKPILOT << fname
00390             << ": No conduit library "
00391             << library
00392             << " found."
00393             << endl;
00394 #endif
00395         fStack->raiseWidget(BROKEN_CONDUIT);
00396         warnNoLibrary(p);
00397         return;
00398     }
00399 
00400     QStringList a;
00401     a.append(CSL1("modal"));
00402 
00403     // QObject *o = f->create(this, 0L, "ConduitConfig",a);
00404     QObject *o = f->create(fStack, 0L, "ConduitConfigBase", a);
00405     bool oldstyle=false;
00406 
00407     if (!o)
00408     {
00409 #ifdef DEBUG
00410         DEBUGKPILOT << fname
00411             << ": Can't create ConduitConfigBase - must be old conduit."
00412             << endl;
00413 #endif
00414 
00415         o = f->create(fParentWidget,0L,"ConduitConfig",a);
00416         oldstyle=true;
00417 
00418         if (!o)
00419         {
00420 #ifdef DEBUG
00421             DEBUGKPILOT << fname
00422                 << ": No ConduitConfig either."
00423                 << endl;
00424 #endif
00425             KLibLoader::self()->unloadLibrary(
00426                 library);
00427             fStack->raiseWidget(BROKEN_CONDUIT);
00428             warnNoLibrary(p);
00429             return;
00430         }
00431     }
00432 
00433     if (oldstyle)
00434     {
00435         ConduitConfig *d = dynamic_cast<ConduitConfig *>(o);
00436 
00437         if (!d)
00438         {
00439 #ifdef DEBUG
00440             DEBUGKPILOT << fname
00441                 << ": Can't cast to config dialog."
00442                 << endl;
00443 #endif
00444             fStack->raiseWidget(BROKEN_CONDUIT);
00445             warnNoLibrary(p);
00446             return;
00447         }
00448         fStack->raiseWidget(OLD_CONDUIT);
00449         fOldStyleLabel->setText(i18n("<qt>The conduit <i>%1</i> "
00450             "is an old-style conduit. To configure it, "
00451             "click the configure button below.</qt>")
00452                 .arg(p->text(CONDUIT_NAME)));
00453 
00454         fCurrentOldStyle=d;
00455         d->setConfig(&KPilotConfig::getConfig());
00456         d->readSettings();
00457     }
00458     else
00459     {
00460         ConduitConfigBase *d = dynamic_cast<ConduitConfigBase *>(o);
00461 
00462         if (!d)
00463         {
00464 #ifdef DEBUG
00465             DEBUGKPILOT << fname
00466                 << ": Can't cast to config base object."
00467                 << endl;
00468 #endif
00469             fStack->raiseWidget(BROKEN_CONDUIT);
00470             warnNoLibrary(p);
00471             return;
00472         }
00473 
00474         // Remove the config widget from the stack before we can add the new one
00475         QWidget *oldConfigWidget = fStack->widget( NEW_CONDUIT );
00476         if ( oldConfigWidget )
00477         {
00478             fStack->removeWidget( oldConfigWidget );
00479             KPILOT_DELETE( oldConfigWidget );
00480         }
00481         if (fStack->addWidget(d->widget(),NEW_CONDUIT)<0)
00482         {
00483     #ifdef DEBUG
00484             DEBUGKPILOT << fname
00485                 << ": Can't add config widget to stack."
00486                 << endl;
00487     #endif
00488         }
00489         else
00490         {
00491             d->load(&KPilotConfig::getConfig());
00492             fStack->raiseWidget(NEW_CONDUIT);
00493             d->widget()->show();
00494             fCurrentConfig=d;
00495         }
00496     }
00497 }
00498 
00499 bool ConduitConfigWidget::release()
00500 {
00501     FUNCTIONSETUP;
00502     if (fCurrentConfig)
00503     {
00504         if (!fCurrentConfig->maybeSave(&KPilotConfig::getConfig()))
00505             return false;
00506         fStack->raiseWidget(0);
00507         delete fCurrentConfig;
00508     }
00509     if (fCurrentOldStyle)
00510     {
00511         fStack->raiseWidget(0);
00512         delete fCurrentOldStyle;
00513     }
00514     if (fCurrentConduit)
00515     {
00516         KLibLoader::self()->unloadLibrary(
00517             QFile::encodeName(fCurrentConduit->text(CONDUIT_LIBRARY)));
00518     }
00519     fCurrentConduit=0L;
00520     fCurrentConfig=0L;
00521     fCurrentOldStyle=0L;
00522     return true;
00523 }
00524 
00525 void ConduitConfigWidget::selected(QListViewItem *p)
00526 {
00527     FUNCTIONSETUP;
00528 #ifdef DEBUG
00529     DEBUGKPILOT << fname << ": "
00530         << ( p ? p->text(CONDUIT_NAME) : CSL1("None") )
00531         << endl;
00532 #endif
00533     if (p!=fCurrentConduit)
00534     {
00535         if (!release())
00536         {
00537             p->setSelected(false);
00538             fCurrentConduit->setSelected(true);
00539             return;
00540         }
00541     }
00542     fCurrentConduit=p;
00543     loadAndConfigure(p);
00544     fStack->adjustSize();
00545 #ifdef DEBUG
00546     DEBUGKPILOT << fname << ": New widget size "
00547         << fStack->size().width() << "x" << fStack->size().height() << endl;
00548     DEBUGKPILOT << fname << ": Parent current size "
00549         << fParentWidget->size().width() << "x"
00550         << fParentWidget->size().height() << endl;
00551 #endif
00552     emit sizeChanged();
00553 #ifdef DEBUG
00554     DEBUGKPILOT << fname << ": Parent new size "
00555         << fParentWidget->size().width() << "x"
00556         << fParentWidget->size().height() << endl;
00557 #endif
00558 
00559 }
00560 
00561 void ConduitConfigWidget::configure()
00562 {
00563     if (!fCurrentOldStyle)
00564     {
00565         loadAndConfigure(fConduitList->selectedItem());
00566     }
00567     if (fCurrentOldStyle)
00568     {
00569         fCurrentOldStyle->exec();
00570     }
00571 }
00572 
00573 void ConduitConfigWidget::warnNoExec(const QListViewItem * p)
00574 {
00575     FUNCTIONSETUP;
00576 
00577     QString msg = i18n("<qt>No library could be "
00578         "found for the conduit %1. This means that the "
00579         "conduit was not installed properly.</qt>")
00580         .arg(p->text(CONDUIT_NAME));
00581 
00582 #ifdef DEBUG
00583     DEBUGKPILOT << fname << ": No library for " 
00584         << p->text(CONDUIT_NAME) << endl;
00585 #endif
00586 
00587     KMessageBox::error(fParentWidget, msg, i18n("Conduit Error"));
00588 }
00589 
00590 void ConduitConfigWidget::warnNoLibrary(const QListViewItem *p)
00591 {
00592     FUNCTIONSETUP;
00593 
00594     QString msg = i18n("<qt>There was a problem loading the library "
00595         "for the conduit %1. This means that the "
00596         "conduit was not installed properly.</qt>")
00597         .arg(p->text(CONDUIT_NAME));
00598 
00599 #ifdef DEBUG
00600     DEBUGKPILOT << fname << ": Can't load library for "
00601         << p->text(CONDUIT_NAME) << endl;
00602 #endif
00603 
00604     KMessageBox::error(fParentWidget, msg, i18n("Conduit Error"));
00605 }
00606 
00607 /* virtual */ void ConduitConfigWidget::commitChanges()
00608 {
00609     FUNCTIONSETUP;
00610     
00611     // Only new-style conduits have changes that need to be commited
00612     // old-style conduits have their own config dlg which commits them itself
00613     if ( fStack->id( fStack->visibleWidget())==NEW_CONDUIT )
00614     {
00615         fCurrentConfig->commit(&KPilotConfig::getConfig());
00616     }
00617 
00618     QStringList activeConduits;
00619     const QCheckListItem *p =
00620         dynamic_cast<QCheckListItem *>(fConduitList->firstChild());
00621     KPilotConfigSettings & config = KPilotConfig::getConfig();
00622 
00623 
00624 
00625     while (p)
00626     {
00627         if (p->isOn())
00628         {
00629             activeConduits.append(p->text(CONDUIT_DESKTOP));
00630         }
00631         p = dynamic_cast<QCheckListItem *>(p->nextSibling());
00632     }
00633     config.setConduitGroup().setInstalledConduits(activeConduits);
00634     config.sync();
00635 }
00636 
00637 
00638 
00639 
KDE Logo
This file is part of the documentation for kpilot Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat May 1 11:36:46 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003