2 This file is part of libkdepim.
4 Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
5 Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
23 #include "kcmdesignerfields.h"
29 #include <KFileDialog>
32 #include <KMessageBox>
35 #include <KStandardDirs>
38 #include <kio/netaccess.h>
45 #include <QPushButton>
48 #include <QtDesigner/QFormBuilder>
49 #include <QHBoxLayout>
51 #include <QVBoxLayout>
61 class PageItem
: public Q3CheckListItem
64 PageItem( Q3ListView
*parent
, const QString
&path
)
65 : Q3CheckListItem( parent
, "", Q3CheckListItem::CheckBox
),
66 mPath( path
), mIsActive( false )
68 mName
= path
.mid( path
.lastIndexOf( '/' ) + 1 );
71 f
.open(QFile::ReadOnly
);
73 QWidget
*wdg
= builder
.load( &f
, 0 );
76 setText( 0, wdg
->windowTitle() );
78 QPixmap pm
= QPixmap::grabWidget( wdg
);
79 QImage img
= pm
.toImage().scaled( 300, 300, Qt::KeepAspectRatio
, Qt::SmoothTransformation
);
80 mPreview
= QPixmap::fromImage(img
);
82 QMap
<QString
, QString
> allowedTypes
;
83 allowedTypes
.insert( "QLineEdit", i18n( "Text" ) );
84 allowedTypes
.insert( "QTextEdit", i18n( "Text" ) );
85 allowedTypes
.insert( "QSpinBox", i18n( "Numeric Value" ) );
86 allowedTypes
.insert( "QCheckBox", i18n( "Boolean" ) );
87 allowedTypes
.insert( "QComboBox", i18n( "Selection" ) );
88 allowedTypes
.insert( "QDateTimeEdit", i18n( "Date & Time" ) );
89 allowedTypes
.insert( "KLineEdit", i18n( "Text" ) );
90 allowedTypes
.insert( "KTextEdit", i18n( "Text" ) );
91 allowedTypes
.insert( "KDateTimeWidget", i18n( "Date & Time" ) );
92 allowedTypes
.insert( "KDatePicker", i18n( "Date" ) );
94 QList
<QWidget
*> list
= wdg
->findChildren
<QWidget
*>();
96 Q_FOREACH( it
, list
) {
97 if ( allowedTypes
.contains( it
->metaObject()->className() ) ) {
98 QString name
= it
->objectName();
99 if ( name
.startsWith( "X_" ) ) {
100 new Q3ListViewItem( this, name
,
101 allowedTypes
[ it
->metaObject()->className() ],
102 it
->metaObject()->className(),
111 QString
name() const { return mName
; }
112 QString
path() const { return mPath
; }
119 void setIsActive( bool isActive
) { mIsActive
= isActive
; }
120 bool isActive() const { return mIsActive
; }
123 void paintBranches( QPainter
*p
, const QColorGroup
& cg
, int w
, int y
, int h
)
125 Q3ListViewItem::paintBranches( p
, cg
, w
, y
, h
);
138 KCMDesignerFields::KCMDesignerFields( const KComponentData
&instance
, QWidget
*parent
, const QStringList
&args
)
139 : KCModule( instance
, parent
, args
)
145 ,mDesignerButton(NULL
)
147 KAboutData
*about
= new KAboutData( I18N_NOOP( "KCMDesignerfields" ), 0,
148 ki18n( "Qt Designer Fields Dialog" ),
149 0, KLocalizedString(), KAboutData::License_LGPL
,
150 ki18n( "(c), 2004 Tobias Koenig" ) );
152 about
->addAuthor( ki18n("Tobias Koenig"), KLocalizedString(), "tokoe@kde.org" );
153 about
->addAuthor( ki18n("Cornelius Schumacher"), KLocalizedString(), "schumacher@kde.org" );
154 setAboutData( about
);
157 void KCMDesignerFields::delayedInit()
159 kDebug() <<"KCMDesignerFields::delayedInit()";
163 connect( mPageView
, SIGNAL( selectionChanged( Q3ListViewItem
* ) ),
164 this, SLOT( updatePreview( Q3ListViewItem
* ) ) );
165 connect( mPageView
, SIGNAL( clicked( Q3ListViewItem
* ) ),
166 this, SLOT( itemClicked( Q3ListViewItem
* ) ) );
168 connect( mDeleteButton
, SIGNAL( clicked() ),
169 this, SLOT( deleteFile() ) );
170 connect( mImportButton
, SIGNAL( clicked() ),
171 this, SLOT( importFile() ) );
172 connect( mDesignerButton
, SIGNAL( clicked() ),
173 this, SLOT( startDesigner() ) );
177 // Install a dirwatcher that will detect newly created or removed designer files
178 KDirWatch
*dw
= new KDirWatch( this );
179 KStandardDirs::makeDir( localUiDir() );
180 dw
->addDir( localUiDir(), KDirWatch::WatchFiles
);
181 connect( dw
, SIGNAL( created(const QString
&) ), SLOT( rebuildList() ) );
182 connect( dw
, SIGNAL( deleted(const QString
&) ), SLOT( rebuildList() ) );
183 connect( dw
, SIGNAL( dirty(const QString
&) ), SLOT( rebuildList() ) );
186 void KCMDesignerFields::deleteFile()
188 Q3ListViewItem
*item
= mPageView
->selectedItem();
190 PageItem
*pageItem
= static_cast<PageItem
*>( item
->parent() ? item
->parent() : item
);
191 if (KMessageBox::warningContinueCancel(this,
192 i18n( "<qt>Do you really want to delete '<b>%1</b>'?</qt>", pageItem
->text(0) ), "", KStandardGuiItem::del() )
193 == KMessageBox::Continue
)
194 KIO::NetAccess::del( pageItem
->path(), 0 );
196 // The actual view refresh will be done automagically by the slots connected to kdirwatch
199 void KCMDesignerFields::importFile()
201 KUrl src
= KFileDialog::getOpenFileName( QDir::homePath(), i18n("*.ui|Designer Files"),
202 this, i18n("Import Page") );
203 KUrl dest
= localUiDir();
204 QDir().mkpath( localUiDir() );
205 dest
.setFileName(src
.fileName());
206 KIO::Job
*job
= KIO::file_copy( src
, dest
, -1, KIO::Overwrite
);
207 KIO::NetAccess::synchronousRun( job
, this );
209 // The actual view refresh will be done automagically by the slots connected to kdirwatch
213 void KCMDesignerFields::loadUiFiles()
215 const QStringList list
= KGlobal::dirs()->findAllResources( "data", uiPath() + "/*.ui",
216 KStandardDirs::Recursive
|
217 KStandardDirs::NoDuplicates
);
218 for ( QStringList::ConstIterator it
= list
.constBegin(); it
!= list
.constEnd(); ++it
) {
219 new PageItem( mPageView
, *it
);
223 void KCMDesignerFields::rebuildList()
225 // If nothing is initialized there is no need to do something
227 QStringList ai
= saveActivePages();
235 void KCMDesignerFields::loadActivePages(const QStringList
& ai
)
237 Q3ListViewItemIterator
it( mPageView
);
238 while ( it
.current() ) {
239 if ( it
.current()->parent() == 0 ) {
240 PageItem
*item
= static_cast<PageItem
*>( it
.current() );
241 if ( ai
.contains( item
->name() ) ) {
243 item
->setIsActive( true );
251 void KCMDesignerFields::load()
253 // see KCModule::showEvent()
257 loadActivePages( readActivePages() );
260 QStringList
KCMDesignerFields::saveActivePages()
262 Q3ListViewItemIterator
it( mPageView
, Q3ListViewItemIterator::Checked
|
263 Q3ListViewItemIterator::Selectable
);
265 QStringList activePages
;
266 while ( it
.current() ) {
267 if ( it
.current()->parent() == 0 ) {
268 PageItem
*item
= static_cast<PageItem
*>( it
.current() );
269 activePages
.append( item
->name() );
278 void KCMDesignerFields::save()
280 writeActivePages( saveActivePages() );
283 void KCMDesignerFields::defaults()
287 void KCMDesignerFields::initGUI()
289 QVBoxLayout
*layout
= new QVBoxLayout( this );
290 layout
->setSpacing( KDialog::spacingHint() );
291 layout
->setMargin( KDialog::marginHint() );
293 bool noDesigner
= KStandardDirs::findExe("designer").isEmpty();
298 i18n("<qt><b>Warning:</b> Qt Designer could not be found. It is probably not "
299 "installed. You will only be able to import existing designer files.</qt>");
300 QLabel
*lbl
= new QLabel( txt
, this );
301 layout
->addWidget( lbl
);
304 QHBoxLayout
*hbox
= new QHBoxLayout();
305 layout
->addLayout( hbox
);
306 hbox
->setSpacing( KDialog::spacingHint() );
308 mPageView
= new K3ListView( this );
309 mPageView
->addColumn( i18n( "Available Pages" ) );
310 mPageView
->setRootIsDecorated( true );
311 mPageView
->setAllColumnsShowFocus( true );
312 mPageView
->setFullWidth( true );
313 hbox
->addWidget( mPageView
);
314 QTimer::singleShot( 0, mPageView
, SLOT(triggerUpdate()) );
316 Q3GroupBox
*box
= new Q3GroupBox(1, Qt::Horizontal
, i18n("Preview of Selected Page"), this );
318 mPagePreview
= new QLabel( box
);
319 mPagePreview
->setMinimumWidth( 300 );
321 mPageDetails
= new QLabel( box
);
323 hbox
->addWidget( box
);
327 hbox
= new QHBoxLayout();
328 layout
->addLayout( hbox
);
329 hbox
->setSpacing( KDialog::spacingHint() );
331 QString cwHowto
= i18n("<qt><p>This section allows you to add your own GUI"
332 " Elements ('<i>Widgets</i>') to store your own values"
333 " into %1. Proceed as described below:</p>"
335 "<li>Click on '<i>Edit with Qt Designer</i>'</li>"
336 "<li>In the dialog, select '<i>Widget</i>', then click <i>OK</i></li>"
337 "<li>Add your widgets to the form</li>"
338 "<li>Save the file in the directory proposed by Qt Designer</li>"
339 "<li>Close Qt Designer</li>"
341 "<p>In case you already have a designer file (*.ui) located"
342 " somewhere on your hard disk, simply choose '<i>Import Page</i>'</p>"
343 "<p><b>Important:</b> The name of each input widget you place within"
344 " the form must start with '<i>X_</i>'; so if you want the widget to"
345 " correspond to your custom entry '<i>X-Foo</i>', set the widget's"
346 " <i>name</i> property to '<i>X_Foo</i>'.</p>"
347 "<p><b>Important:</b> The widget will edit custom fields with an"
348 " application name of %2. To change the application name"
349 " to be edited, set the widget name in Qt Designer.</p></qt>",
350 applicationName(), applicationName() );
352 QLabel
*activeLabel
= new QLabel(
353 i18n( "<a href=\"whatsthis:%1\">How does this work?</a>" , cwHowto
), this );
354 activeLabel
->setTextInteractionFlags(Qt::LinksAccessibleByMouse
|Qt::LinksAccessibleByKeyboard
);
355 connect( activeLabel
, SIGNAL(linkActivated(QString
)),
356 this, SLOT(showWhatsThis(QString
)) );
357 hbox
->addWidget( activeLabel
);
360 // ### why is this needed? Looks like a KActiveLabel bug...
361 activeLabel
->setSizePolicy( QSizePolicy::Preferred
, QSizePolicy::Maximum
);
363 hbox
->addStretch( 1 );
365 mDeleteButton
= new QPushButton( i18n( "Delete Page" ), this);
366 mDeleteButton
->setEnabled( false );
367 hbox
->addWidget( mDeleteButton
);
368 mImportButton
= new QPushButton( i18n( "Import Page..." ), this);
369 hbox
->addWidget( mImportButton
);
370 mDesignerButton
= new QPushButton( i18n( "Edit with Qt Designer..." ), this );
371 hbox
->addWidget( mDesignerButton
);
374 mDesignerButton
->setEnabled( false );
377 void KCMDesignerFields::updatePreview( Q3ListViewItem
*item
)
379 bool widgetItemSelected
= false;
382 if ( item
->parent() ) {
383 QString details
= QString( "<qt><table>"
384 "<tr><td align=\"right\"><b>%1</b></td><td>%2</td></tr>"
385 "<tr><td align=\"right\"><b>%3</b></td><td>%4</td></tr>"
386 "<tr><td align=\"right\"><b>%5</b></td><td>%6</td></tr>"
387 "<tr><td align=\"right\"><b>%7</b></td><td>%8</td></tr>"
389 .arg( i18n( "Key:" ) )
390 .arg( item
->text( 0 ).replace("X_","X-") )
391 .arg( i18n( "Type:" ) )
392 .arg( item
->text( 1 ) )
393 .arg( i18n( "Classname:" ) )
394 .arg( item
->text( 2 ) )
395 .arg( i18n( "Description:" ) )
396 .arg( item
->text( 3 ) );
398 mPageDetails
->setText( details
);
400 PageItem
*pageItem
= static_cast<PageItem
*>( item
->parent() );
401 mPagePreview
->setWindowIcon( pageItem
->preview() );
403 mPageDetails
->setText( QString() );
405 PageItem
*pageItem
= static_cast<PageItem
*>( item
);
406 mPagePreview
->setWindowIcon( pageItem
->preview() );
408 widgetItemSelected
= true;
411 mPagePreview
->setFrameStyle( QFrame::Panel
| QFrame::Sunken
);
413 mPagePreview
->setWindowIcon( QPixmap() );
414 mPagePreview
->setFrameStyle( 0 );
415 mPageDetails
->setText( QString() );
418 mDeleteButton
->setEnabled( widgetItemSelected
);
421 void KCMDesignerFields::itemClicked( Q3ListViewItem
*item
)
423 if ( !item
|| item
->parent() != 0 )
426 PageItem
*pageItem
= static_cast<PageItem
*>( item
);
428 if ( pageItem
->isOn() != pageItem
->isActive() ) {
429 emit
changed( true );
430 pageItem
->setIsActive( pageItem
->isOn() );
434 void KCMDesignerFields::startDesigner()
436 QString cmdLine
= "designer";
438 // check if path exists and create one if not.
439 QString cepPath
= localUiDir();
440 if( !KGlobal::dirs()->exists(cepPath
) ) {
441 KIO::NetAccess::mkdir( cepPath
, this );
444 // finally jump there
445 chdir(cepPath
.toLocal8Bit());
447 Q3ListViewItem
*item
= mPageView
->selectedItem();
449 PageItem
*pageItem
= static_cast<PageItem
*>( item
->parent() ? item
->parent() : item
);
450 cmdLine
+= ' ' + KShell::quoteArg( pageItem
->path() );
453 KRun::runCommand( cmdLine
, topLevelWidget());
456 void KCMDesignerFields::showWhatsThis(const QString
&href
)
458 if (href
.startsWith("whatsthis:")) {
459 QPoint pos
= QCursor::pos();
460 QWhatsThis::showText(pos
, href
.mid(10), this);
464 #include "kcmdesignerfields.moc"