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 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
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
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
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
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
00402 QString cepPath = kabLocalDir() +"contacteditorpages";
00403 if( !KGlobal::dirs()->exists(cepPath) ) {
00404 KIO::NetAccess::mkdir( cepPath, this );
00405 }
00406
00407
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"