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   KGlobal::locale()->insertCatalogue("kcmkabconfig");
00140   initGUI();
00141 
00142   connect( mPageView, SIGNAL( selectionChanged( QListViewItem* ) ),
00143            this, SLOT( updatePreview( QListViewItem* ) ) );
00144   connect( mPageView, SIGNAL( clicked( QListViewItem* ) ),
00145            this, SLOT( itemClicked( QListViewItem* ) ) );
00146 
00147   connect( mDeleteButton, SIGNAL( clicked() ),
00148            this, SLOT( deleteFile() ) );
00149   connect( mImportButton, SIGNAL( clicked() ),
00150            this, SLOT( importFile() ) );
00151   connect( mDesignerButton, SIGNAL( clicked() ),
00152            this, SLOT( startDesigner() ) );
00153 
00154   load();
00155 
00156   // Install a dirwatcher that will detect newly created or removed designer files
00157   KDirWatch *dw = new KDirWatch( this );
00158   dw->addDir( kabLocalDir() + "contacteditorpages", true );
00159   connect( dw, SIGNAL( created(const QString&) ), SLOT( rebuildList() ) );
00160   connect( dw, SIGNAL( deleted(const QString&) ), SLOT( rebuildList() ) );
00161   connect( dw, SIGNAL( dirty(const QString&) ),   SLOT( rebuildList() ) );
00162 
00163 }
00164 
00165 void KCMKabCustomFields::deleteFile()
00166 {
00167   QListViewItem *item = mPageView->selectedItem();
00168   if ( item ) {
00169     PageItem *pageItem = static_cast<PageItem*>( item->parent() ? item->parent() : item );
00170     if (KMessageBox::warningContinueCancel(this,
00171          i18n( "<qt>Do you really want to delete '<b>%1</b>'?</qt>").arg( pageItem->text(0) ), "", KGuiItem( i18n("&Delete"), "editdelete") )
00172          == KMessageBox::Continue)
00173       KIO::NetAccess::del( pageItem->path(), 0 );
00174   }
00175   // The actual view refresh will be done automagically by the slots connected to kdirwatch
00176 }
00177 
00178 void KCMKabCustomFields::importFile()
00179 {
00180   KURL src = KFileDialog::getOpenFileName( QDir::homeDirPath(), i18n("*.ui|Designer Files"),
00181                                               this, i18n("Import Page") );
00182   KURL dest = kabLocalDir() + "contacteditorpages/";
00183   dest.setFileName(src.fileName());
00184   KIO::NetAccess::file_copy( src, dest, -1, true, false, this );
00185   // The actual view refresh will be done automagically by the slots connected to kdirwatch
00186 }
00187 
00188 
00189 void KCMKabCustomFields::loadUiFiles()
00190 {
00191   QStringList list = KGlobal::dirs()->findAllResources( "data", "kaddressbook/contacteditorpages/*.ui", true, true );
00192   for ( QStringList::iterator it = list.begin(); it != list.end(); ++it ) {
00193     new PageItem( mPageView, *it );
00194   }
00195 }
00196 
00197 void KCMKabCustomFields::rebuildList()
00198 {
00199   QStringList ai = saveActivePages();
00200   updatePreview( 0 );
00201   mPageView->clear();
00202   loadUiFiles();
00203   loadActivePages(ai);
00204 }
00205 
00206 void KCMKabCustomFields::loadActivePages(const QStringList& ai)
00207 {
00208   QListViewItemIterator it( mPageView );
00209   while ( it.current() ) {
00210     if ( it.current()->parent() == 0 ) {
00211       PageItem *item = static_cast<PageItem*>( it.current() );
00212       if ( ai.find( item->name() ) != ai.end() ) {
00213         item->setOn( true );
00214         item->setIsActive( true );
00215       }
00216     }
00217 
00218     ++it;
00219   }
00220 }
00221 
00222 void KCMKabCustomFields::load()
00223 {
00224   loadActivePages(KABPrefs::instance()->mAdvancedCustomFields);
00225 }
00226 
00227 QStringList KCMKabCustomFields::saveActivePages()
00228 {
00229   QListViewItemIterator it( mPageView, QListViewItemIterator::Checked |
00230                             QListViewItemIterator::Selectable );
00231 
00232   QStringList activePages;
00233   while ( it.current() ) {
00234     if ( it.current()->parent() == 0 ) {
00235       PageItem *item = static_cast<PageItem*>( it.current() );
00236       activePages.append( item->name() );
00237     }
00238 
00239     ++it;
00240   }
00241 
00242   return activePages;
00243 }
00244 
00245 void KCMKabCustomFields::save()
00246 {
00247   KABPrefs::instance()->mAdvancedCustomFields =  saveActivePages();
00248   KABPrefs::instance()->writeConfig();
00249 }
00250 
00251 void KCMKabCustomFields::defaults()
00252 {
00253 }
00254 
00255 void KCMKabCustomFields::initGUI()
00256 {
00257   QVBoxLayout *layout = new QVBoxLayout( this, KDialog::marginHint(),
00258                                          KDialog::spacingHint() );
00259 
00260   bool noDesigner = KStandardDirs::findExe("designer").isEmpty();
00261 
00262   if ( noDesigner )
00263   {
00264     QString txt =
00265       i18n("<qt><b>Warning:</b> Qt Designer could not be found. It is probably not "
00266          "installed. You will only be able to import existing designer files!</qt>");
00267     QLabel *lbl = new QLabel( txt, this );
00268     layout->addWidget( lbl );
00269   }
00270 
00271   QHBoxLayout *hbox = new QHBoxLayout( layout, KDialog::spacingHint() );
00272 
00273   mPageView = new KListView( this );
00274   mPageView->addColumn( i18n( "Available Pages" ) );
00275   mPageView->setRootIsDecorated( true );
00276   mPageView->setAllColumnsShowFocus( true );
00277   mPageView->setFullWidth( true );
00278   hbox->addWidget( mPageView );
00279 
00280   QGroupBox *box = new QGroupBox(1, Qt::Horizontal, i18n("Preview of Selected Page"), this );
00281 
00282   mPagePreview = new QLabel( box );
00283   mPagePreview->setMinimumWidth( 300 );
00284 
00285   mPageDetails = new QLabel( box );
00286 
00287   hbox->addWidget( box );
00288 
00289   loadUiFiles();
00290 
00291   hbox = new QHBoxLayout( layout, KDialog::spacingHint() );
00292 
00293   QString cwHowto = i18n("<qt><p>This section allows you to add your own GUI"
00294                          "  Elements ('<i>Widgets</i>') to store your own values"
00295                          " into the address book. Proceed as described below:</p>"
00296                          "<ol>"
00297                          "<li>Click on '<i>Edit with Qt Designer</i>'"
00298                          "<li>In the dialog, select '<i>Widget</i>', then click <i>OK</i>"
00299                          "<li>Add your widgets to the form"
00300                          "<li>Save the file in the directory proposed by Qt Designer"
00301                          "<li>Close Qt Designer"
00302                          "</ol>"
00303                          "<p>In case you already have a designer file (*.ui) located"
00304                          " somewhere on your hard disk, simply choose '<i>Import Page</i>'</p>"
00305                          "<p><b>Important:</b> The name of each input widget you place within"
00306                          " the form must start with '<i>X_</i>'; so if you want the widget to"
00307                          " correspond to your custom entry '<i>X-Foo</i>', set the widget's"
00308                          " <i>name</i> property to '<i>X_Foo</i>'.</p>"
00309                          "<p><b>Important:</b> The widget will edit custom fields with an"
00310                          " application name of KADDRESSBOOK.  To change the application name"
00311                          " to be edited, set the widget name in Qt Designer.</p></qt>" );
00312 
00313   KActiveLabel *activeLabel = new KActiveLabel(
00314       i18n( "<a href=\"whatsthis:%1\">How does this work?</a>" ).arg(cwHowto), this );
00315   hbox->addWidget( activeLabel );
00316 
00317   // ### why is this needed? Looks like a KActiveLabel bug...
00318   activeLabel->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Maximum );
00319 
00320   hbox->addStretch( 1 );
00321 
00322   mDeleteButton = new QPushButton( i18n( "Delete Page" ), this);
00323   mDeleteButton->setEnabled( false );
00324   hbox->addWidget( mDeleteButton );
00325   mImportButton = new QPushButton( i18n( "Import Page..." ), this);
00326   hbox->addWidget( mImportButton );
00327   mDesignerButton = new QPushButton( i18n( "Edit with Qt Designer..." ), this );
00328   hbox->addWidget( mDesignerButton );
00329 
00330   if ( noDesigner )
00331     mDesignerButton->setEnabled( false );
00332 }
00333 
00334 void KCMKabCustomFields::updatePreview( QListViewItem *item )
00335 {
00336   bool widgetItemSelected = false;
00337 
00338   if ( item ) {
00339     if ( item->parent() ) {
00340       QString details = QString( "<qt><table>"
00341                                  "<tr><td align=\"right\"><b>%1</b></td><td>%2</td></tr>"
00342                                  "<tr><td align=\"right\"><b>%3</b></td><td>%4</td></tr>"
00343                                  "<tr><td align=\"right\"><b>%5</b></td><td>%6</td></tr>"
00344                                  "<tr><td align=\"right\"><b>%7</b></td><td>%8</td></tr>"
00345                                  "</table></qt>" )
00346                                 .arg( i18n( "vCard key:" ) )
00347                                 .arg( item->text( 0 ).replace("X_","X-") )
00348                                 .arg( i18n( "Type:" ) )
00349                                 .arg( item->text( 1 ) )
00350                                 .arg( i18n( "Classname:" ) )
00351                                 .arg( item->text( 2 ) )
00352                                 .arg( i18n( "Description:" ) )
00353                                 .arg( item->text( 3 ) );
00354 
00355       mPageDetails->setText( details );
00356 
00357       PageItem *pageItem = static_cast<PageItem*>( item->parent() );
00358       mPagePreview->setPixmap( pageItem->preview() );
00359     } else {
00360       mPageDetails->setText( QString::null );
00361 
00362       PageItem *pageItem = static_cast<PageItem*>( item );
00363       mPagePreview->setPixmap( pageItem->preview() );
00364 
00365       widgetItemSelected = true;
00366     }
00367 
00368     mPagePreview->setFrameStyle( QFrame::Panel | QFrame::Sunken );
00369   } else {
00370     mPagePreview->setPixmap( QPixmap() );
00371     mPagePreview->setFrameStyle( 0 );
00372     mPageDetails->setText( QString::null );
00373   }
00374 
00375   mDeleteButton->setEnabled( widgetItemSelected );
00376 }
00377 
00378 void KCMKabCustomFields::itemClicked( QListViewItem *item )
00379 {
00380   if ( !item || item->parent() != 0 )
00381     return;
00382 
00383   PageItem *pageItem = static_cast<PageItem*>( item );
00384 
00385   if ( pageItem->isOn() != pageItem->isActive() ) {
00386     emit changed( true );
00387     pageItem->setIsActive( pageItem->isOn() );
00388   }
00389 }
00390 
00391 QString KCMKabCustomFields::kabLocalDir()
00392 {
00393   QStringList kabdirs = locateLocal("data", "kaddressbook/");
00394   return kabdirs.grep( QRegExp( "^"+KGlobal::dirs()->localkdedir() ) ).first();
00395 }
00396 
00397 void KCMKabCustomFields::startDesigner()
00398 {
00399   QString cmdLine = "designer";
00400 
00401   // check if path exists and create one if not.
00402   QString cepPath = kabLocalDir() +"contacteditorpages";
00403   if( !KGlobal::dirs()->exists(cepPath) ) {
00404     KIO::NetAccess::mkdir( cepPath, this );
00405   }
00406 
00407   // finnally jump there
00408   chdir(cepPath.local8Bit());
00409 
00410   QListViewItem *item = mPageView->selectedItem();
00411   if ( item ) {
00412     PageItem *pageItem = static_cast<PageItem*>( item->parent() ? item->parent() : item );
00413     cmdLine += " " + pageItem->path();
00414   }
00415 
00416   KRun::runCommand( cmdLine );
00417 }
00418 
00419 const KAboutData* KCMKabCustomFields::aboutData() const
00420 {
00421   KAboutData *about = new KAboutData( I18N_NOOP( "kcmkabcustomfields" ),
00422                                       I18N_NOOP( "KAddressBook Custom Fields Dialog" ),
00423                                       0, 0, KAboutData::License_GPL,
00424                                       I18N_NOOP( "(c), 2004 Tobias Koenig" ) );
00425 
00426   about->addAuthor( "Tobias Koenig", 0, "tokoe@kde.org" );
00427 
00428   return about;
00429 }
00430 
00431 #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 Fri Dec 21 14:24:11 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003