00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
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
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
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
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
00401 QString cepPath = kabLocalDir() +"contacteditorpages";
00402 if( !KGlobal::dirs()->exists(cepPath) ) {
00403 KIO::NetAccess::mkdir( cepPath, this );
00404 }
00405
00406
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"