/* This file is part of KOrganizer. Copyright (c) 2004 Tobias Koenig Copyright (c) 2004 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kcmdesignerfields.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class PageItem : public QTreeWidgetItem { public: PageItem( QTreeWidget *parent, const QString &path ) : QTreeWidgetItem( parent ), mPath( path ), mIsActive( false ) { setFlags( flags() | Qt::ItemIsUserCheckable ); setCheckState( 0, Qt::Unchecked ); mName = path.mid( path.lastIndexOf( QLatin1Char('/') ) + 1 ); QFile f( mPath ); if (!f.open( QFile::ReadOnly ) ) return; QUiLoader builder; QWidget *wdg = builder.load( &f, 0 ); f.close(); if ( wdg ) { setText( 0, wdg->windowTitle() ); QPixmap pm = QPixmap::grabWidget( wdg ); QImage img = pm.toImage().scaled( 300, 300, Qt::KeepAspectRatio, Qt::SmoothTransformation ); mPreview = QPixmap::fromImage(img); QMap allowedTypes; allowedTypes.insert( QLatin1String("QLineEdit"), i18n( "Text" ) ); allowedTypes.insert( QLatin1String("QTextEdit"), i18n( "Text" ) ); allowedTypes.insert( QLatin1String("QSpinBox"), i18n( "Numeric Value" ) ); allowedTypes.insert( QLatin1String("QCheckBox"), i18n( "Boolean" ) ); allowedTypes.insert( QLatin1String("QComboBox"), i18n( "Selection" ) ); allowedTypes.insert( QLatin1String("QDateTimeEdit"), i18n( "Date & Time" ) ); allowedTypes.insert( QLatin1String("KLineEdit"), i18n( "Text" ) ); allowedTypes.insert( QLatin1String("KTextEdit"), i18n( "Text" ) ); allowedTypes.insert( QLatin1String("KDateTimeWidget"), i18n( "Date & Time" ) ); allowedTypes.insert( QLatin1String("KDatePicker"), i18n( "Date" ) ); QList list = wdg->findChildren(); QWidget *it; Q_FOREACH ( it, list ) { if ( allowedTypes.contains( QLatin1String(it->metaObject()->className()) ) ) { QString name = it->objectName(); if ( name.startsWith( QLatin1String( "X_" ) ) ) { new QTreeWidgetItem( this, QStringList() << name << allowedTypes[ QLatin1String(it->metaObject()->className()) ] << QLatin1String(it->metaObject()->className()) << it->whatsThis() ); } } } } } QString name() const { return mName; } QString path() const { return mPath; } QPixmap preview() { return mPreview; } void setIsActive( bool isActive ) { mIsActive = isActive; } bool isActive() const { return mIsActive; } bool isOn() const { return checkState( 0 ) == Qt::Checked; } private: QString mName; QString mPath; QPixmap mPreview; bool mIsActive; }; KCMDesignerFields::KCMDesignerFields( const KComponentData &instance, QWidget *parent, const QVariantList &args ) : KCModule( instance, parent, args ), mPageView( 0 ), mPagePreview( 0 ), mPageDetails( 0 ), mDeleteButton( 0 ), mImportButton( 0 ), mDesignerButton( 0 ) { KAboutData *about = new KAboutData( I18N_NOOP( "KCMDesignerfields" ), 0, ki18n( "Qt Designer Fields Dialog" ), 0, KLocalizedString(), KAboutData::License_LGPL, ki18n( "(c), 2004 Tobias Koenig" ) ); about->addAuthor( ki18n( "Tobias Koenig" ), KLocalizedString(), "tokoe@kde.org" ); about->addAuthor( ki18n( "Cornelius Schumacher" ), KLocalizedString(), "schumacher@kde.org" ); setAboutData( about ); } void KCMDesignerFields::delayedInit() { kDebug() << "KCMDesignerFields::delayedInit()"; initGUI(); connect( mPageView, SIGNAL(itemSelectionChanged()), this, SLOT(updatePreview()) ); connect( mPageView, SIGNAL(itemClicked(QTreeWidgetItem*,int)), this, SLOT(itemClicked(QTreeWidgetItem*)) ); connect( mDeleteButton, SIGNAL(clicked()), this, SLOT(deleteFile()) ); connect( mImportButton, SIGNAL(clicked()), this, SLOT(importFile()) ); connect( mDesignerButton, SIGNAL(clicked()), this, SLOT(startDesigner()) ); load(); // Install a dirwatcher that will detect newly created or removed designer files KDirWatch *dw = new KDirWatch( this ); KStandardDirs::makeDir( localUiDir() ); dw->addDir( localUiDir(), KDirWatch::WatchFiles ); connect( dw, SIGNAL(created(QString)), SLOT(rebuildList()) ); connect( dw, SIGNAL(deleted(QString)), SLOT(rebuildList()) ); connect( dw, SIGNAL(dirty(QString)), SLOT(rebuildList()) ); } void KCMDesignerFields::deleteFile() { foreach ( QTreeWidgetItem *item, mPageView->selectedItems() ) { PageItem *pageItem = static_cast( item->parent() ? item->parent() : item ); if ( KMessageBox::warningContinueCancel( this, i18n( "Do you really want to delete '%1'?", pageItem->text(0) ), QString(), KStandardGuiItem::del() ) == KMessageBox::Continue ) { KIO::NetAccess::del( pageItem->path(), 0 ); } } // The actual view refresh will be done automagically by the slots connected to kdirwatch } void KCMDesignerFields::importFile() { KUrl src = KFileDialog::getOpenFileName( QDir::homePath(), i18n( "*.ui|Designer Files" ), this, i18n( "Import Page" ) ); KUrl dest = localUiDir(); QDir().mkpath( localUiDir() ); dest.setFileName( src.fileName() ); KIO::Job *job = KIO::file_copy( src, dest, -1, KIO::Overwrite ); KIO::NetAccess::synchronousRun( job, this ); // The actual view refresh will be done automagically by the slots connected to kdirwatch } void KCMDesignerFields::loadUiFiles() { const QStringList list = KGlobal::dirs()->findAllResources( "data", uiPath() + QLatin1String("/*.ui"), KStandardDirs::Recursive | KStandardDirs::NoDuplicates ); for ( QStringList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it ) { new PageItem( mPageView, *it ); } } void KCMDesignerFields::rebuildList() { // If nothing is initialized there is no need to do something if ( mPageView ) { QStringList ai = saveActivePages(); updatePreview(); mPageView->clear(); loadUiFiles(); loadActivePages(ai); } } void KCMDesignerFields::loadActivePages( const QStringList &ai ) { QTreeWidgetItemIterator it( mPageView ); while ( *it ) { if ( (*it)->parent() == 0 ) { PageItem *item = static_cast( *it ); if ( ai.contains( item->name() ) ) { item->setCheckState( 0, Qt::Checked ); item->setIsActive( true ); } } ++it; } } void KCMDesignerFields::load() { // see KCModule::showEvent() if ( !mPageView ) { delayedInit(); } loadActivePages( readActivePages() ); } QStringList KCMDesignerFields::saveActivePages() { QTreeWidgetItemIterator it( mPageView, QTreeWidgetItemIterator::Checked | QTreeWidgetItemIterator::Selectable ); QStringList activePages; while ( *it ) { if ( (*it)->parent() == 0 ) { PageItem *item = static_cast( *it ); activePages.append( item->name() ); } ++it; } return activePages; } void KCMDesignerFields::save() { writeActivePages( saveActivePages() ); } void KCMDesignerFields::defaults() { } void KCMDesignerFields::initGUI() { QVBoxLayout *layout = new QVBoxLayout( this ); layout->setSpacing( KDialog::spacingHint() ); layout->setMargin( KDialog::marginHint() ); bool noDesigner = KStandardDirs::findExe( QLatin1String("designer") ).isEmpty(); if ( noDesigner ) { QString txt = i18n( "Warning: Qt Designer could not be found. It is probably not " "installed. You will only be able to import existing designer files." ); QLabel *lbl = new QLabel( txt, this ); layout->addWidget( lbl ); } QHBoxLayout *hbox = new QHBoxLayout(); layout->addLayout( hbox ); hbox->setSpacing( KDialog::spacingHint() ); mPageView = new QTreeWidget( this ); mPageView->setHeaderLabel( i18n( "Available Pages" ) ); mPageView->setRootIsDecorated( true ); mPageView->setAllColumnsShowFocus( true ); mPageView->header()->setResizeMode( QHeaderView::Stretch ); hbox->addWidget( mPageView ); QGroupBox *box = new QGroupBox( i18n( "Preview of Selected Page" ), this ); QVBoxLayout *boxLayout = new QVBoxLayout( box ); mPagePreview = new QLabel( box ); mPagePreview->setMinimumWidth( 300 ); boxLayout->addWidget( mPagePreview ); mPageDetails = new QLabel( box ); boxLayout->addWidget( mPageDetails ); boxLayout->addStretch( 1 ); hbox->addWidget( box ); loadUiFiles(); hbox = new QHBoxLayout(); layout->addLayout( hbox ); hbox->setSpacing( KDialog::spacingHint() ); QString cwHowto = i18n( "

This section allows you to add your own GUI" " Elements ('Widgets') to store your own values" " into %1. Proceed as described below:

" "
    " "
  1. Click on 'Edit with Qt Designer'
  2. " "
  3. In the dialog, select 'Widget', then click OK
  4. " "
  5. Add your widgets to the form
  6. " "
  7. Save the file in the directory proposed by Qt Designer
  8. " "
  9. Close Qt Designer
  10. " "
" "

In case you already have a designer file (*.ui) located" " somewhere on your hard disk, simply choose 'Import Page'

" "

Important: The name of each input widget you place within" " the form must start with 'X_'; so if you want the widget to" " correspond to your custom entry 'X-Foo', set the widget's" " name property to 'X_Foo'.

" "

Important: The widget will edit custom fields with an" " application name of %2. To change the application name" " to be edited, set the widget name in Qt Designer.

", applicationName(), applicationName() ); QLabel *activeLabel = new QLabel( i18n( "How does this work?", cwHowto ), this ); activeLabel->setTextInteractionFlags( Qt::LinksAccessibleByMouse| Qt::LinksAccessibleByKeyboard ); activeLabel->setContextMenuPolicy(Qt::NoContextMenu); connect( activeLabel, SIGNAL(linkActivated(QString)), this, SLOT(showWhatsThis(QString)) ); hbox->addWidget( activeLabel ); // ### why is this needed? Looks like a KActiveLabel bug... activeLabel->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Maximum ); hbox->addStretch( 1 ); mDeleteButton = new QPushButton( i18n( "Delete Page" ), this ); mDeleteButton->setEnabled( false ); hbox->addWidget( mDeleteButton ); mImportButton = new QPushButton( i18n( "Import Page..." ), this ); hbox->addWidget( mImportButton ); mDesignerButton = new QPushButton( i18n( "Edit with Qt Designer..." ), this ); hbox->addWidget( mDesignerButton ); if ( noDesigner ) { mDesignerButton->setEnabled( false ); } } void KCMDesignerFields::updatePreview() { QTreeWidgetItem *item = 0; if ( mPageView->selectedItems().size() == 1 ) { item = mPageView->selectedItems().first(); } bool widgetItemSelected = false; if ( item ) { if ( item->parent() ) { QString details = QString::fromLatin1( "" "" "" "" "" "
%1%2
%3%4
%5%6
%7%8
" ) .arg( i18n( "Key:" ) ) .arg( item->text( 0 ).replace( QLatin1String("X_"),QLatin1String("X-") ) ) .arg( i18n( "Type:" ) ) .arg( item->text( 1 ) ) .arg( i18n( "Classname:" ) ) .arg( item->text( 2 ) ) .arg( i18n( "Description:" ) ) .arg( item->text( 3 ) ); mPageDetails->setText( details ); PageItem *pageItem = static_cast( item->parent() ); mPagePreview->setWindowIcon( pageItem->preview() ); } else { mPageDetails->setText( QString() ); PageItem *pageItem = static_cast( item ); mPagePreview->setWindowIcon( pageItem->preview() ); widgetItemSelected = true; } mPagePreview->setFrameStyle( QFrame::StyledPanel | QFrame::Sunken ); } else { mPagePreview->setWindowIcon( QPixmap() ); mPagePreview->setFrameStyle( 0 ); mPageDetails->setText( QString() ); } mDeleteButton->setEnabled( widgetItemSelected ); } void KCMDesignerFields::itemClicked( QTreeWidgetItem *item ) { if ( !item || item->parent() != 0 ) { return; } PageItem *pageItem = static_cast( item ); if ( pageItem->isOn() != pageItem->isActive() ) { emit changed( true ); pageItem->setIsActive( pageItem->isOn() ); } } void KCMDesignerFields::startDesigner() { QString cmdLine = QLatin1String("designer"); // check if path exists and create one if not. QString cepPath = localUiDir(); if( !KGlobal::dirs()->exists(cepPath) ) { KIO::NetAccess::mkdir( cepPath, this ); } // finally jump there QDir::setCurrent( QLatin1String(cepPath.toLocal8Bit()) ); QTreeWidgetItem *item = 0; if ( mPageView->selectedItems().size() == 1 ) { item = mPageView->selectedItems().first(); } if ( item ) { PageItem *pageItem = static_cast( item->parent() ? item->parent() : item ); cmdLine += QLatin1Char(' ') + KShell::quoteArg( pageItem->path() ); } KRun::runCommand( cmdLine, topLevelWidget() ); } void KCMDesignerFields::showWhatsThis( const QString &href ) { if ( href.startsWith( QLatin1String( "whatsthis:" ) ) ) { QPoint pos = QCursor::pos(); QWhatsThis::showText( pos, href.mid( 10 ), this ); } }