00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <unistd.h>
00024
00025 #include <qimage.h>
00026 #include <qlabel.h>
00027 #include <qlayout.h>
00028 #include <qobjectlist.h>
00029 #include <qpixmap.h>
00030 #include <qpushbutton.h>
00031 #include <qwhatsthis.h>
00032 #include <qgroupbox.h>
00033 #include <qwidgetfactory.h>
00034 #include <qregexp.h>
00035 #include <qtimer.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 <kprocess.h>
00050 #include <kio/netaccess.h>
00051
00052 #include "kcmdesignerfields.h"
00053
00054 using namespace KPIM;
00055
00056 class PageItem : public QCheckListItem
00057 {
00058 public:
00059 PageItem( QListView *parent, const QString &path )
00060 : QCheckListItem( parent, "", QCheckListItem::CheckBox ),
00061 mPath( path ), mIsActive( false )
00062 {
00063 mName = path.mid( path.findRev( '/' ) + 1 );
00064
00065 QWidget *wdg = QWidgetFactory::create( mPath, 0, 0 );
00066 if ( wdg ) {
00067 setText( 0, wdg->caption() );
00068
00069 QPixmap pm = QPixmap::grabWidget( wdg );
00070 QImage img = pm.convertToImage().smoothScale( 300, 300, QImage::ScaleMin );
00071 mPreview = img;
00072
00073 QObjectList *list = wdg->queryList( "QWidget" );
00074 QObjectListIt it( *list );
00075
00076 QMap<QString, QString> allowedTypes;
00077 allowedTypes.insert( "QLineEdit", i18n( "Text" ) );
00078 allowedTypes.insert( "QTextEdit", i18n( "Text" ) );
00079 allowedTypes.insert( "QSpinBox", i18n( "Numeric Value" ) );
00080 allowedTypes.insert( "QCheckBox", i18n( "Boolean" ) );
00081 allowedTypes.insert( "QComboBox", i18n( "Selection" ) );
00082 allowedTypes.insert( "QDateTimeEdit", i18n( "Date & Time" ) );
00083 allowedTypes.insert( "KLineEdit", i18n( "Text" ) );
00084 allowedTypes.insert( "KDateTimeWidget", i18n( "Date & Time" ) );
00085 allowedTypes.insert( "KDatePicker", i18n( "Date" ) );
00086
00087 while ( it.current() ) {
00088 if ( allowedTypes.find( it.current()->className() ) != allowedTypes.end() ) {
00089 QString name = it.current()->name();
00090 if ( name.startsWith( "X_" ) ) {
00091 new QListViewItem( this, name,
00092 allowedTypes[ it.current()->className() ],
00093 it.current()->className(),
00094 QWhatsThis::textFor( static_cast<QWidget*>( it.current() ) ) );
00095 }
00096 }
00097
00098 ++it;
00099 }
00100
00101 delete list;
00102 }
00103 }
00104
00105 QString name() const { return mName; }
00106 QString path() const { return mPath; }
00107
00108 QPixmap preview()
00109 {
00110 return mPreview;
00111 }
00112
00113 void setIsActive( bool isActive ) { mIsActive = isActive; }
00114 bool isActive() const { return mIsActive; }
00115
00116 protected:
00117 void paintBranches( QPainter *p, const QColorGroup & cg, int w, int y, int h )
00118 {
00119 QListViewItem::paintBranches( p, cg, w, y, h );
00120 }
00121
00122 private:
00123 QString mName;
00124 QString mPath;
00125 QPixmap mPreview;
00126 bool mIsActive;
00127 };
00128
00129 KCMDesignerFields::KCMDesignerFields( QWidget *parent, const char *name )
00130 : KCModule( parent, name )
00131 {
00132 QTimer::singleShot( 0, this, SLOT( delayedInit() ) );
00133
00134 KAboutData *about = new KAboutData( I18N_NOOP( "KCMDesignerfields" ),
00135 I18N_NOOP( "Qt Designer Fields Dialog" ),
00136 0, 0, KAboutData::License_LGPL,
00137 I18N_NOOP( "(c), 2004 Tobias Koenig" ) );
00138
00139 about->addAuthor( "Tobias Koenig", 0, "tokoe@kde.org" );
00140 about->addAuthor( "Cornelius Schumacher", 0, "schumacher@kde.org" );
00141 setAboutData( about );
00142 }
00143
00144 void KCMDesignerFields::delayedInit()
00145 {
00146 kdDebug() << "KCMDesignerFields::delayedInit()" << endl;
00147
00148 initGUI();
00149
00150 connect( mPageView, SIGNAL( selectionChanged( QListViewItem* ) ),
00151 this, SLOT( updatePreview( QListViewItem* ) ) );
00152 connect( mPageView, SIGNAL( clicked( QListViewItem* ) ),
00153 this, SLOT( itemClicked( QListViewItem* ) ) );
00154
00155 connect( mDeleteButton, SIGNAL( clicked() ),
00156 this, SLOT( deleteFile() ) );
00157 connect( mImportButton, SIGNAL( clicked() ),
00158 this, SLOT( importFile() ) );
00159 connect( mDesignerButton, SIGNAL( clicked() ),
00160 this, SLOT( startDesigner() ) );
00161
00162 load();
00163
00164
00165 KDirWatch *dw = new KDirWatch( this );
00166 dw->addDir( localUiDir(), true );
00167 connect( dw, SIGNAL( created(const QString&) ), SLOT( rebuildList() ) );
00168 connect( dw, SIGNAL( deleted(const QString&) ), SLOT( rebuildList() ) );
00169 connect( dw, SIGNAL( dirty(const QString&) ), SLOT( rebuildList() ) );
00170 }
00171
00172 void KCMDesignerFields::deleteFile()
00173 {
00174 QListViewItem *item = mPageView->selectedItem();
00175 if ( item ) {
00176 PageItem *pageItem = static_cast<PageItem*>( item->parent() ? item->parent() : item );
00177 if (KMessageBox::warningContinueCancel(this,
00178 i18n( "<qt>Do you really want to delete '<b>%1</b>'?</qt>").arg( pageItem->text(0) ), "", KStdGuiItem::del() )
00179 == KMessageBox::Continue)
00180 KIO::NetAccess::del( pageItem->path(), 0 );
00181 }
00182
00183 }
00184
00185 void KCMDesignerFields::importFile()
00186 {
00187 KURL src = KFileDialog::getOpenFileName( QDir::homeDirPath(), i18n("*.ui|Designer Files"),
00188 this, i18n("Import Page") );
00189 KURL dest = localUiDir();
00190 dest.setFileName(src.fileName());
00191 KIO::NetAccess::file_copy( src, dest, -1, true, false, this );
00192
00193 }
00194
00195
00196 void KCMDesignerFields::loadUiFiles()
00197 {
00198 QStringList list = KGlobal::dirs()->findAllResources( "data", uiPath() + "/*.ui", true, true );
00199 for ( QStringList::iterator it = list.begin(); it != list.end(); ++it ) {
00200 new PageItem( mPageView, *it );
00201 }
00202 }
00203
00204 void KCMDesignerFields::rebuildList()
00205 {
00206 QStringList ai = saveActivePages();
00207 updatePreview( 0 );
00208 mPageView->clear();
00209 loadUiFiles();
00210 loadActivePages(ai);
00211 }
00212
00213 void KCMDesignerFields::loadActivePages(const QStringList& ai)
00214 {
00215 QListViewItemIterator it( mPageView );
00216 while ( it.current() ) {
00217 if ( it.current()->parent() == 0 ) {
00218 PageItem *item = static_cast<PageItem*>( it.current() );
00219 if ( ai.find( item->name() ) != ai.end() ) {
00220 item->setOn( true );
00221 item->setIsActive( true );
00222 }
00223 }
00224
00225 ++it;
00226 }
00227 }
00228
00229 void KCMDesignerFields::load()
00230 {
00231 loadActivePages( readActivePages() );
00232 }
00233
00234 QStringList KCMDesignerFields::saveActivePages()
00235 {
00236 QListViewItemIterator it( mPageView, QListViewItemIterator::Checked |
00237 QListViewItemIterator::Selectable );
00238
00239 QStringList activePages;
00240 while ( it.current() ) {
00241 if ( it.current()->parent() == 0 ) {
00242 PageItem *item = static_cast<PageItem*>( it.current() );
00243 activePages.append( item->name() );
00244 }
00245
00246 ++it;
00247 }
00248
00249 return activePages;
00250 }
00251
00252 void KCMDesignerFields::save()
00253 {
00254 writeActivePages( saveActivePages() );
00255 }
00256
00257 void KCMDesignerFields::defaults()
00258 {
00259 }
00260
00261 void KCMDesignerFields::initGUI()
00262 {
00263 QVBoxLayout *layout = new QVBoxLayout( this, KDialog::marginHint(),
00264 KDialog::spacingHint() );
00265
00266 bool noDesigner = KStandardDirs::findExe("designer").isEmpty();
00267
00268 if ( noDesigner )
00269 {
00270 QString txt =
00271 i18n("<qt><b>Warning:</b> Qt Designer could not be found. It is probably not "
00272 "installed. You will only be able to import existing designer files.</qt>");
00273 QLabel *lbl = new QLabel( txt, this );
00274 layout->addWidget( lbl );
00275 }
00276
00277 QHBoxLayout *hbox = new QHBoxLayout( layout, KDialog::spacingHint() );
00278
00279 mPageView = new KListView( this );
00280 mPageView->addColumn( i18n( "Available Pages" ) );
00281 mPageView->setRootIsDecorated( true );
00282 mPageView->setAllColumnsShowFocus( true );
00283 mPageView->setFullWidth( true );
00284 hbox->addWidget( mPageView );
00285
00286 QGroupBox *box = new QGroupBox(1, Qt::Horizontal, i18n("Preview of Selected Page"), this );
00287
00288 mPagePreview = new QLabel( box );
00289 mPagePreview->setMinimumWidth( 300 );
00290
00291 mPageDetails = new QLabel( box );
00292
00293 hbox->addWidget( box );
00294
00295 loadUiFiles();
00296
00297 hbox = new QHBoxLayout( layout, KDialog::spacingHint() );
00298
00299 QString cwHowto = i18n("<qt><p>This section allows you to add your own GUI"
00300 " Elements ('<i>Widgets</i>') to store your own values"
00301 " into %1. Proceed as described below:</p>"
00302 "<ol>"
00303 "<li>Click on '<i>Edit with Qt Designer</i>'"
00304 "<li>In the dialog, select '<i>Widget</i>', then click <i>OK</i>"
00305 "<li>Add your widgets to the form"
00306 "<li>Save the file in the directory proposed by Qt Designer"
00307 "<li>Close Qt Designer"
00308 "</ol>"
00309 "<p>In case you already have a designer file (*.ui) located"
00310 " somewhere on your hard disk, simply choose '<i>Import Page</i>'</p>"
00311 "<p><b>Important:</b> The name of each input widget you place within"
00312 " the form must start with '<i>X_</i>'; so if you want the widget to"
00313 " correspond to your custom entry '<i>X-Foo</i>', set the widget's"
00314 " <i>name</i> property to '<i>X_Foo</i>'.</p>"
00315 "<p><b>Important:</b> The widget will edit custom fields with an"
00316 " application name of %2. To change the application name"
00317 " to be edited, set the widget name in Qt Designer.</p></qt>" )
00318 .arg( applicationName(), applicationName() );
00319
00320 KActiveLabel *activeLabel = new KActiveLabel(
00321 i18n( "<a href=\"whatsthis:%1\">How does this work?</a>" ).arg(cwHowto), this );
00322 hbox->addWidget( activeLabel );
00323
00324
00325 activeLabel->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Maximum );
00326
00327 hbox->addStretch( 1 );
00328
00329 mDeleteButton = new QPushButton( i18n( "Delete Page" ), this);
00330 mDeleteButton->setEnabled( false );
00331 hbox->addWidget( mDeleteButton );
00332 mImportButton = new QPushButton( i18n( "Import Page..." ), this);
00333 hbox->addWidget( mImportButton );
00334 mDesignerButton = new QPushButton( i18n( "Edit with Qt Designer..." ), this );
00335 hbox->addWidget( mDesignerButton );
00336
00337 if ( noDesigner )
00338 mDesignerButton->setEnabled( false );
00339
00340
00341
00342 mPageView->show();
00343 box->show();
00344 activeLabel->show();
00345 mDeleteButton->show();
00346 mImportButton->show();
00347 mDesignerButton->show();
00348 }
00349
00350 void KCMDesignerFields::updatePreview( QListViewItem *item )
00351 {
00352 bool widgetItemSelected = false;
00353
00354 if ( item ) {
00355 if ( item->parent() ) {
00356 QString details = QString( "<qt><table>"
00357 "<tr><td align=\"right\"><b>%1</b></td><td>%2</td></tr>"
00358 "<tr><td align=\"right\"><b>%3</b></td><td>%4</td></tr>"
00359 "<tr><td align=\"right\"><b>%5</b></td><td>%6</td></tr>"
00360 "<tr><td align=\"right\"><b>%7</b></td><td>%8</td></tr>"
00361 "</table></qt>" )
00362 .arg( i18n( "Key:" ) )
00363 .arg( item->text( 0 ).replace("X_","X-") )
00364 .arg( i18n( "Type:" ) )
00365 .arg( item->text( 1 ) )
00366 .arg( i18n( "Classname:" ) )
00367 .arg( item->text( 2 ) )
00368 .arg( i18n( "Description:" ) )
00369 .arg( item->text( 3 ) );
00370
00371 mPageDetails->setText( details );
00372
00373 PageItem *pageItem = static_cast<PageItem*>( item->parent() );
00374 mPagePreview->setPixmap( pageItem->preview() );
00375 } else {
00376 mPageDetails->setText( QString::null );
00377
00378 PageItem *pageItem = static_cast<PageItem*>( item );
00379 mPagePreview->setPixmap( pageItem->preview() );
00380
00381 widgetItemSelected = true;
00382 }
00383
00384 mPagePreview->setFrameStyle( QFrame::Panel | QFrame::Sunken );
00385 } else {
00386 mPagePreview->setPixmap( QPixmap() );
00387 mPagePreview->setFrameStyle( 0 );
00388 mPageDetails->setText( QString::null );
00389 }
00390
00391 mDeleteButton->setEnabled( widgetItemSelected );
00392 }
00393
00394 void KCMDesignerFields::itemClicked( QListViewItem *item )
00395 {
00396 if ( !item || item->parent() != 0 )
00397 return;
00398
00399 PageItem *pageItem = static_cast<PageItem*>( item );
00400
00401 if ( pageItem->isOn() != pageItem->isActive() ) {
00402 emit changed( true );
00403 pageItem->setIsActive( pageItem->isOn() );
00404 }
00405 }
00406
00407 void KCMDesignerFields::startDesigner()
00408 {
00409 QString cmdLine = "designer";
00410
00411
00412 QString cepPath = localUiDir();
00413 if( !KGlobal::dirs()->exists(cepPath) ) {
00414 KIO::NetAccess::mkdir( cepPath, this );
00415 }
00416
00417
00418 chdir(cepPath.local8Bit());
00419
00420 QListViewItem *item = mPageView->selectedItem();
00421 if ( item ) {
00422 PageItem *pageItem = static_cast<PageItem*>( item->parent() ? item->parent() : item );
00423 cmdLine += " " + KProcess::quote( pageItem->path() );
00424 }
00425
00426 KRun::runCommand( cmdLine );
00427 }
00428
00429 #include "kcmdesignerfields.moc"