kaddressbook Library API Documentation

kcmkabcustomfields.cpp

00001 /*
00002     This file is part of KAddressbook.
00003     Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
00004 
00005     This program is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program; if not, write to the Free Software
00017     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 
00019     As a special exception, permission is given to link this program
00020     with any edition of Qt, and distribute the resulting executable,
00021     without including the source code for Qt in the source distribution.
00022 */
00023 
00024 #include <unistd.h>
00025 
00026 #include <qimage.h>
00027 #include <qlabel.h>
00028 #include <qlayout.h>
00029 #include <qobjectlist.h>
00030 #include <qpixmap.h>
00031 #include <qpushbutton.h>
00032 #include <qwhatsthis.h>
00033 #include <qgroupbox.h>
00034 #include <qwidgetfactory.h>
00035 #include <qregexp.h>
00036 
00037 #include <kaboutdata.h>
00038 #include <kdebug.h>
00039 #include <kdialog.h>
00040 #include <kglobal.h>
00041 #include <klistview.h>
00042 #include <klocale.h>
00043 #include <krun.h>
00044 #include <kstandarddirs.h>
00045 #include <kactivelabel.h>
00046 #include <kdirwatch.h>
00047 #include <kfiledialog.h>
00048 #include <kmessagebox.h>
00049 #include <kio/netaccess.h>
00050 
00051 #include "kabprefs.h"
00052 
00053 #include "kcmkabcustomfields.h"
00054 
00055 extern "C"
00056 {
00057   KCModule *create_kabcustomfields( QWidget *parent, const char * ) {
00058     return new KCMKabCustomFields( parent, "kcmkabcustomfields" );
00059   }
00060 }
00061 
00062 class PageItem : public QCheckListItem
00063 {
00064   public:
00065     PageItem( QListView *parent, const QString &path )
00066       : QCheckListItem( parent, "", QCheckListItem::CheckBox ),
00067         mPath( path ), mIsActive( false )
00068     {
00069       mName = path.mid( path.findRev( '/' ) + 1 );
00070 
00071       QWidget *wdg = QWidgetFactory::create( mPath, 0, 0 );
00072       if ( wdg ) {
00073         setText( 0, wdg->caption() );
00074 
00075         QPixmap pm = QPixmap::grabWidget( wdg );
00076         QImage img = pm.convertToImage().smoothScale( 300, 300, QImage::ScaleMin );
00077         mPreview = img;
00078 
00079         QObjectList *list = wdg->queryList( "QWidget" );
00080         QObjectListIt it( *list );
00081 
00082         QMap<QString, QString> allowedTypes;
00083         allowedTypes.insert( "QLineEdit", i18n( "Text" ) );
00084         allowedTypes.insert( "QTextEdit", i18n( "Text" ) );
00085         allowedTypes.insert( "QSpinBox", i18n( "Numeric Value" ) );
00086         allowedTypes.insert( "QCheckBox", i18n( "Boolean" ) );
00087         allowedTypes.insert( "QComboBox", i18n( "Selection" ) );
00088         allowedTypes.insert( "QDateTimeEdit", i18n( "Date & Time" ) );
00089         allowedTypes.insert( "KLineEdit", i18n( "Text" ) );
00090         allowedTypes.insert( "KDateTimeWidget", i18n( "Date & Time" ) );
00091         allowedTypes.insert( "KDatePicker", i18n( "Date" ) );
00092 
00093         while ( it.current() ) {
00094           if ( allowedTypes.find( it.current()->className() ) != allowedTypes.end() ) {
00095             QString name = it.current()->name();
00096             if ( name.startsWith( "X_" ) ) {
00097               new QListViewItem( this, name,
00098                                  allowedTypes[ it.current()->className() ],
00099                                  it.current()->className(),
00100                                  QWhatsThis::textFor( static_cast<QWidget*>( it.current() ) ) );
00101             }
00102           }
00103 
00104           ++it;
00105         }
00106 
00107         delete list;
00108       } else
00109         delete wdg;
00110     }
00111 
00112     QString name() const { return mName; }
00113     QString path() const { return mPath; }
00114 
00115     QPixmap preview()
00116     {
00117       return mPreview;
00118     }
00119 
00120     void setIsActive( bool isActive ) { mIsActive = isActive; }
00121     bool isActive() const { return mIsActive; }
00122 
00123   protected:
00124     void paintBranches( QPainter *p, const QColorGroup & cg, int w, int y, int h )
00125     {
00126       QListViewItem::paintBranches( p, cg, w, y, h );
00127     }
00128 
00129   private:
00130     QString mName;
00131     QString mPath;
00132     QPixmap mPreview;
00133     bool mIsActive;
00134 };
00135 
00136 KCMKabCustomFields::KCMKabCustomFields( QWidget *parent, const char *name )
00137   : KCModule( parent, name )
00138 {
00139   initGUI();
00140 
00141   connect( mPageView, SIGNAL( selectionChanged( QListViewItem* ) ),
00142            this, SLOT( updatePreview( QListViewItem* ) ) );
00143   connect( mPageView, SIGNAL( clicked( QListViewItem* ) ),
00144            this, SLOT( itemClicked( QListViewItem* ) ) );
00145 
00146   connect( mDeleteButton, SIGNAL( clicked() ),
00147            this, SLOT( deleteFile() ) );
00148   connect( mImportButton, SIGNAL( clicked() ),
00149            this, SLOT( importFile() ) );
00150   connect( mDesignerButton, SIGNAL( clicked() ),
00151            this, SLOT( startDesigner() ) );
00152 
00153   load();
00154 
00155   // Install a dirwatcher that will detect newly created or removed designer files
00156   KDirWatch *dw = new KDirWatch( this );
00157   dw->addDir( kabLocalDir() + "contacteditorpages", true );
00158   connect( dw, SIGNAL( created(const QString&) ), SLOT( rebuildList() ) );
00159   connect( dw, SIGNAL( deleted(const QString&) ), SLOT( rebuildList() ) );
00160   connect( dw, SIGNAL( dirty(const QString&) ),   SLOT( rebuildList() ) );
00161 
00162 }
00163 
00164 void KCMKabCustomFields::deleteFile()
00165 {
00166   QListViewItem *item = mPageView->selectedItem();
00167   if ( item ) {
00168     PageItem *pageItem = static_cast<PageItem*>( item->parent() ? item->parent() : item );
00169     if (KMessageBox::warningContinueCancel(this,
00170          i18n( "<qt>Do you really want to delete '<b>%1</b>'?</qt>").arg( pageItem->text(0) ), "", KGuiItem( i18n("&Delete"), "editdelete") )
00171          == KMessageBox::Continue)
00172       KIO::NetAccess::del( pageItem->path(), 0 );
00173   }
00174   // The actual view refresh will be done automagically by the slots connected to kdirwatch
00175 }
00176 
00177 void KCMKabCustomFields::importFile()
00178 {
00179   KURL src = KFileDialog::getOpenFileName( QDir::homeDirPath(), i18n("*.ui|Designer Files"),
00180                                               this, i18n("Import Page") );
00181   KURL dest = kabLocalDir() + "contacteditorpages/";
00182   dest.setFileName(src.fileName());
00183   KIO::NetAccess::file_copy( src, dest, -1, true, false, this );
00184   // The actual view refresh will be done automagically by the slots connected to kdirwatch
00185 }
00186 
00187 
00188 void KCMKabCustomFields::loadUiFiles()
00189 {
00190   QStringList list = KGlobal::dirs()->findAllResources( "data", "kaddressbook/contacteditorpages/*.ui", true, true );
00191   for ( QStringList::iterator it = list.begin(); it != list.end(); ++it ) {
00192     new PageItem( mPageView, *it );
00193   }
00194 }
00195 
00196 void KCMKabCustomFields::rebuildList()
00197 {
00198   QStringList ai = saveActivePages();
00199   updatePreview( 0 );
00200   mPageView->clear();
00201   loadUiFiles();
00202   loadActivePages(ai);
00203 }
00204 
00205 void KCMKabCustomFields::loadActivePages(const QStringList& ai)
00206 {
00207   QListViewItemIterator it( mPageView );
00208   while ( it.current() ) {
00209     if ( it.current()->parent() == 0 ) {
00210       PageItem *item = static_cast<PageItem*>( it.current() );
00211       if ( ai.find( item->name() ) != ai.end() ) {
00212         item->setOn( true );
00213         item->setIsActive( true );
00214       }
00215     }
00216 
00217     ++it;
00218   }
00219 }
00220 
00221 void KCMKabCustomFields::load()
00222 {
00223   loadActivePages(KABPrefs::instance()->mAdvancedCustomFields);
00224 }
00225 
00226 QStringList KCMKabCustomFields::saveActivePages()
00227 {
00228   QListViewItemIterator it( mPageView, QListViewItemIterator::Checked |
00229                             QListViewItemIterator::Selectable );
00230 
00231   QStringList activePages;
00232   while ( it.current() ) {
00233     if ( it.current()->parent() == 0 ) {
00234       PageItem *item = static_cast<PageItem*>( it.current() );
00235       activePages.append( item->name() );
00236     }
00237 
00238     ++it;
00239   }
00240 
00241   return activePages;
00242 }
00243 
00244 void KCMKabCustomFields::save()
00245 {
00246   KABPrefs::instance()->mAdvancedCustomFields =  saveActivePages();
00247   KABPrefs::instance()->writeConfig();
00248 }
00249 
00250 void KCMKabCustomFields::defaults()
00251 {
00252 }
00253 
00254 void KCMKabCustomFields::initGUI()
00255 {
00256   QVBoxLayout *layout = new QVBoxLayout( this, KDialog::marginHint(),
00257                                          KDialog::spacingHint() );
00258 
00259   bool noDesigner = KStandardDirs::findExe("designer").isEmpty();
00260 
00261   if ( noDesigner )
00262   {
00263     QString txt =
00264       i18n("<qt><b>Warning:</b> Qt Designer could not be found. It is probably not "
00265          "installed. You will only be able to import existing designer files!</qt>");
00266     QLabel *lbl = new QLabel( txt, this );
00267     layout->addWidget( lbl );
00268   }
00269 
00270   QHBoxLayout *hbox = new QHBoxLayout( layout, KDialog::spacingHint() );
00271 
00272   mPageView = new KListView( this );
00273   mPageView->addColumn( i18n( "Available Pages" ) );
00274   mPageView->setRootIsDecorated( true );
00275   mPageView->setAllColumnsShowFocus( true );
00276   mPageView->setFullWidth( true );
00277   hbox->addWidget( mPageView );
00278 
00279   QGroupBox *box = new QGroupBox(1, Qt::Horizontal, i18n("Preview of Selected Page"), this );
00280 
00281   mPagePreview = new QLabel( box );
00282   mPagePreview->setMinimumWidth( 300 );
00283 
00284   mPageDetails = new QLabel( box );
00285 
00286   hbox->addWidget( box );
00287 
00288   loadUiFiles();
00289 
00290   hbox = new QHBoxLayout( layout, KDialog::spacingHint() );
00291 
00292   QString cwHowto = i18n("<qt><p>This section allows you to add your own GUI"
00293                          "  Elements ('<i>Widgets</i>') to store your own values"
00294                          " into the address book. Proceed as described below:</p>"
00295                          "<ol>"
00296                          "<li>Click on '<i>Edit with Qt Designer</i>'"
00297                          "<li>In the dialog, select '<i>Widget</i>', then click <i>OK</i>"
00298                          "<li>Add your widgets to the form"
00299                          "<li>Save the file in the directory proposed by Qt Designer"
00300                          "<li>Close Qt Designer"
00301                          "</ol>"
00302                          "<p>In case you already have a designer file (*.ui) located"
00303                          " somewhere on your hard disk, simply choose '<i>Import Page</i>'</p>"
00304                          "<p><b>Important:</b> The name of each input widget you place within"
00305                          " the form must start with '<i>X_</i>'; so if you want the widget to"
00306                          " correspond to your custom entry '<i>X-Foo</i>', set the widget's"
00307                          " <i>name</i> property to '<i>X_Foo</i>'.</p>"
00308                          "<p><b>Important:</b> The widget will edit custom fields with an"
00309                          " application name of KADDRESSBOOK.  To change the application name"
00310                          " to be edited, set the widget name in Qt Designer.</p></qt>" );
00311 
00312   KActiveLabel *activeLabel = new KActiveLabel(
00313       i18n( "<a href=\"whatsthis:%1\">How does this work?</a>" ).arg(cwHowto), this );
00314   hbox->addWidget( activeLabel );
00315 
00316   // ### why is this needed? Looks like a KActiveLabel bug...
00317   activeLabel->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Maximum );
00318 
00319   hbox->addStretch( 1 );
00320 
00321   mDeleteButton = new QPushButton( i18n( "Delete Page" ), this);
00322   mDeleteButton->setEnabled( false );
00323   hbox->addWidget( mDeleteButton );
00324   mImportButton = new QPushButton( i18n( "Import Page..." ), this);
00325   hbox->addWidget( mImportButton );
00326   mDesignerButton = new QPushButton( i18n( "Edit with Qt Designer..." ), this );
00327   hbox->addWidget( mDesignerButton );
00328 
00329   if ( noDesigner )
00330     mDesignerButton->setEnabled( false );
00331 }
00332 
00333 void KCMKabCustomFields::updatePreview( QListViewItem *item )
00334 {
00335   bool widgetItemSelected = false;
00336 
00337   if ( item ) {
00338     if ( item->parent() ) {
00339       QString details = QString( "<qt><table>"
00340                                  "<tr><td align=\"right\"><b>%1</b></td><td>%2</td></tr>"
00341                                  "<tr><td align=\"right\"><b>%3</b></td><td>%4</td></tr>"
00342                                  "<tr><td align=\"right\"><b>%5</b></td><td>%6</td></tr>"
00343                                  "<tr><td align=\"right\"><b>%7</b></td><td>%8</td></tr>"
00344                                  "</table></qt>" )
00345                                 .arg( i18n( "vCard key:" ) )
00346                                 .arg( item->text( 0 ).replace("X_","X-") )
00347                                 .arg( i18n( "Type:" ) )
00348                                 .arg( item->text( 1 ) )
00349                                 .arg( i18n( "Classname:" ) )
00350                                 .arg( item->text( 2 ) )
00351                                 .arg( i18n( "Description:" ) )
00352                                 .arg( item->text( 3 ) );
00353 
00354       mPageDetails->setText( details );
00355 
00356       PageItem *pageItem = static_cast<PageItem*>( item->parent() );
00357       mPagePreview->setPixmap( pageItem->preview() );
00358     } else {
00359       mPageDetails->setText( QString::null );
00360 
00361       PageItem *pageItem = static_cast<PageItem*>( item );
00362       mPagePreview->setPixmap( pageItem->preview() );
00363 
00364       widgetItemSelected = true;
00365     }
00366 
00367     mPagePreview->setFrameStyle( QFrame::Panel | QFrame::Sunken );
00368   } else {
00369     mPagePreview->setPixmap( QPixmap() );
00370     mPagePreview->setFrameStyle( 0 );
00371     mPageDetails->setText( QString::null );
00372   }
00373 
00374   mDeleteButton->setEnabled( widgetItemSelected );
00375 }
00376 
00377 void KCMKabCustomFields::itemClicked( QListViewItem *item )
00378 {
00379   if ( !item || item->parent() != 0 )
00380     return;
00381 
00382   PageItem *pageItem = static_cast<PageItem*>( item );
00383 
00384   if ( pageItem->isOn() != pageItem->isActive() ) {
00385     emit changed( true );
00386     pageItem->setIsActive( pageItem->isOn() );
00387   }
00388 }
00389 
00390 QString KCMKabCustomFields::kabLocalDir()
00391 {
00392   QStringList kabdirs = locateLocal("data", "kaddressbook/");
00393   return kabdirs.grep( QRegExp( "^"+KGlobal::dirs()->localkdedir() ) ).first();
00394 }
00395 
00396 void KCMKabCustomFields::startDesigner()
00397 {
00398   QString cmdLine = "designer";
00399 
00400   // check if path exists and create one if not.
00401   QString cepPath = kabLocalDir() +"contacteditorpages";
00402   if( !KGlobal::dirs()->exists(cepPath) ) {
00403     KIO::NetAccess::mkdir( cepPath, this );
00404   }
00405 
00406   // finnally jump there
00407   chdir(cepPath.local8Bit());
00408 
00409   QListViewItem *item = mPageView->selectedItem();
00410   if ( item ) {
00411     PageItem *pageItem = static_cast<PageItem*>( item->parent() ? item->parent() : item );
00412     cmdLine += " " + pageItem->path();
00413   }
00414 
00415   KRun::runCommand( cmdLine );
00416 }
00417 
00418 const KAboutData* KCMKabCustomFields::aboutData() const
00419 {
00420   KAboutData *about = new KAboutData( I18N_NOOP( "kcmkabcustomfields" ),
00421                                       I18N_NOOP( "KAddressBook Custom Fields Dialog" ),
00422                                       0, 0, KAboutData::License_GPL,
00423                                       I18N_NOOP( "(c), 2004 Tobias Koenig" ) );
00424 
00425   about->addAuthor( "Tobias Koenig", 0, "tokoe@kde.org" );
00426 
00427   return about;
00428 }
00429 
00430 #include "kcmkabcustomfields.moc"
KDE Logo
This file is part of the documentation for kaddressbook Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 23 22:42:47 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003