KDevelop API Documentation

filecreate_part.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *   Copyright (C) 2003 by Julian Rockey                                   *
00003  *   linux@jrockey.com                                                     *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  ***************************************************************************/
00010 
00011 #include <qwhatsthis.h>
00012 #include <qdom.h>
00013 #include <qdir.h>
00014 #include <qfileinfo.h>
00015 #include <qvbox.h>
00016 #include <qtimer.h>
00017 
00018 #include <kdeversion.h>
00019 #include <kiconloader.h>
00020 #include <klocale.h>
00021 #include <kdevgenericfactory.h>
00022 #include <kfiledialog.h>
00023 #include <kdebug.h>
00024 #include <kstandarddirs.h>
00025 #include <kstdaction.h>
00026 #include <kaction.h>
00027 #include <kapplication.h>
00028 #include <kactionclasses.h>
00029 #include <kpopupmenu.h>
00030 #include <kiconloader.h>
00031 
00032 #include "kdevcore.h"
00033 #include "kdevmainwindow.h"
00034 #include "kdevproject.h"
00035 #include "kdevpartcontroller.h"
00036 #include "configwidgetproxy.h"
00037 
00038 #include "filetemplate.h"
00039 #include "domutil.h"
00040 #include "urlutil.h"
00041 
00042 #include "filecreate_widget2.h"
00043 #include "filecreate_widget3.h"
00044 #include "filecreate_part.h"
00045 #include "filecreate_filetype.h"
00046 #include "filecreate_filedialog.h"
00047 #include "filecreate_newfile.h"
00048 #include "fcconfigwidget.h"
00049 
00050 #define PROJECTSETTINGSPAGE 1
00051 #define GLOBALSETTINGSPAGE 2
00052 
00053 static const KAboutData data("kdevfilecreate", I18N_NOOP("New File Wizard"), "1.0");
00054 
00055 typedef KDevGenericFactory<FileCreatePart> FileCreateFactory;
00056 K_EXPORT_COMPONENT_FACTORY( libkdevfilecreate, FileCreateFactory( &data ) )
00057 
00058 using namespace FileCreate;
00059 
00060 FileCreatePart::FileCreatePart(QObject *parent, const char *name, const QStringList & )
00061     : KDevCreateFile("FileCreate", "wizard", parent, name ? name : "FileCreatePart"), m_selectedWidget(-1), m_useSideTab(true), m_subPopups(0)
00062 {
00063   setInstance(FileCreateFactory::instance());
00064   setXMLFile("kdevpart_filecreate.rc");
00065 
00066   connect( core(), SIGNAL(projectOpened()), this, SLOT(slotProjectOpened()) );
00067   connect( core(), SIGNAL(projectClosed()), this, SLOT(slotProjectClosed()) );
00068   
00069     _configProxy = new ConfigWidgetProxy( core() );
00070     _configProxy->createProjectConfigPage( i18n("New File Wizard"), PROJECTSETTINGSPAGE, icon() );
00071     _configProxy->createGlobalConfigPage( i18n("New File Wizard"), GLOBALSETTINGSPAGE, icon() );
00072     connect( _configProxy, SIGNAL(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )), 
00073         this, SLOT(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )) );
00074 
00075 
00076   KToolBarPopupAction * newAction = new KToolBarPopupAction( i18n("&New"), "file_new", CTRL+Qt::Key_N, this, SLOT(slotNewFile()), actionCollection(), "file_new");
00077   newAction->setWhatsThis( i18n("<b>New file</b><p>Creates a new file. Also adds it the project if the <b>Add to project</b> checkbox is turned on.") );
00078   newAction->setToolTip( i18n("Create a new file") );
00079   m_newPopupMenu = newAction->popupMenu();
00080   connect(m_newPopupMenu, SIGNAL(aboutToShow()), this, SLOT(slotAboutToShowNewPopupMenu()));
00081   
00082 //  m_filetypes.setAutoDelete(true);
00083 
00084   m_availableWidgets[0] = new FriendlyWidget(this);
00085   m_availableWidgets[1] = new ListWidget(this);
00086   m_numWidgets = 2;
00087 
00091   selectWidget(1);
00092   
00093   QTimer::singleShot( 0, this, SLOT(slotGlobalInitialize()) );
00094 }
00095 
00096 
00097 FileCreatePart::~FileCreatePart()
00098 {
00099 /*
00100   for(int c=0;c<m_numWidgets;c++){
00101     if (TypeChooser* chooser = m_availableWidgets[c]) {
00102 
00103        if( QWidget* as_widget = dynamic_cast<QWidget*>(chooser) )
00104            mainWindow()->removeView( as_widget );
00105 
00106        delete chooser;
00107     }
00108   }
00109 */  
00110   delete _configProxy;
00111   
00112   m_newPopupMenu->clear();
00113   delete m_subPopups;
00114 }
00115 
00116 void FileCreatePart::insertConfigWidget( const KDialogBase * dlg, QWidget * page, unsigned int pagenumber )
00117 {
00118     kdDebug() << k_funcinfo << endl;
00119     
00120     switch( pagenumber )
00121     {
00122         case PROJECTSETTINGSPAGE:
00123         {
00124             FCConfigWidget* w = new FCConfigWidget( this, false, page, "filecreate config widget" );
00125             connect( dlg, SIGNAL( okClicked( ) ), w, SLOT( accept( ) ) );
00126         }
00127         break;
00128         
00129         case GLOBALSETTINGSPAGE:
00130         {
00131             FCConfigWidget *w = new FCConfigWidget( this, true, page, "filecreate config widget" );
00132             connect(dlg, SIGNAL(okClicked()), w, SLOT(accept()));
00133         }
00134         break;
00135     }
00136 }
00137 
00138 void FileCreatePart::selectWidget(int widgetNumber) {
00139   if (m_selectedWidget==widgetNumber) return;
00140   if (widgetNumber<-1 || widgetNumber>=m_numWidgets) return;
00141   if (setWidget(widgetNumber==-1 ? NULL : m_availableWidgets[widgetNumber]))
00142     m_selectedWidget = widgetNumber;
00143 }
00144 
00145 
00146 bool FileCreatePart::setWidget(TypeChooser * widg) {
00147 
00148   QWidget *as_widget = widg ? dynamic_cast<QWidget*>(widg) : NULL;
00149 
00150   // remove the existing widget
00151   TypeChooser *tc = typeChooserWidget();
00152   if (tc) {
00153     disconnect( tc->signaller(), SIGNAL(filetypeSelected(const FileType *)), this, SLOT(slotFiletypeSelected(const FileType *)) );
00154     QWidget *as_widget2 = dynamic_cast<QWidget*>(tc);
00155     if (as_widget2) {
00156         kdDebug(9034) << "filecreate_part: Removing as_widget2" << endl;
00157       mainWindow()->removeView(as_widget2);
00158     } else
00159       kdWarning(9034) << "WARNING: could not cast to as_widget2" << endl;
00160 
00161   }
00162 
00163   if (widg && as_widget) {
00164     connect( widg->signaller(), SIGNAL(filetypeSelected(const FileType *)), this, SLOT(slotFiletypeSelected(const FileType *)) );
00165     mainWindow()->embedSelectView(as_widget, i18n("New File"), i18n("File creation"));
00166   }
00167 
00168   return true;
00169 }
00170 
00171 void FileCreatePart::refresh() {
00172   if (typeChooserWidget()) typeChooserWidget()->refresh();
00173 }
00174 
00175 void FileCreatePart::slotAboutToShowNewPopupMenu()
00176 {
00177     KIconLoader * m_iconLoader = KGlobal::iconLoader();
00178     m_newPopupMenu->clear();
00179     delete m_subPopups;
00180     m_subPopups = NULL;
00181     int id = 0;
00182     FileType * filetype = m_filetypes.first();
00183     for(; filetype; filetype=m_filetypes.next())
00184     {
00185         if (filetype->enabled())
00186         {
00187             if (filetype->subtypes().count()==0)
00188             {
00189                 QPixmap iconPix = m_iconLoader->loadIcon(
00190                     filetype->icon(), KIcon::Desktop, KIcon::SizeSmall,
00191                     KIcon::DefaultState, NULL, true);
00192                 m_newPopupMenu->insertItem(iconPix, filetype->name(), this,
00193                     SLOT(slotNewFilePopup(int)), 0, ++id );
00194                 m_newPopupMenu->setItemParameter( id, (int)filetype );
00195             } else
00196             {
00197                 KPopupMenu* subMenu = NULL;
00198                 QPtrList<FileType> subtypes = filetype->subtypes();
00199                 for(FileType * subtype = subtypes.first(); subtype; subtype=subtypes.next())
00200                 {
00201                     if (subtype->enabled()){
00202                         if( !subMenu )
00203                             subMenu = new KPopupMenu(0,0);
00204                         QPixmap iconPix = m_iconLoader->loadIcon(
00205                             subtype->icon(), KIcon::Desktop, KIcon::SizeSmall,
00206                             KIcon::DefaultState, NULL, true);
00207                         subMenu->insertItem(iconPix, subtype->name(), this,
00208                             SLOT(slotNewFilePopup(int)), 0, ++id );
00209                         subMenu->setItemParameter( id, (int)filetype );
00210                     }
00211                 }
00212                 if( subMenu )
00213                 {
00214                     if( !m_subPopups )
00215                     {
00216                         m_subPopups = new QPtrList<KPopupMenu>;
00217                         m_subPopups->setAutoDelete(true);
00218                     }
00219                     m_subPopups->append( subMenu );
00220                     m_newPopupMenu->insertItem( filetype->name(), subMenu );
00221                 }
00222             }
00223 
00224         }
00225 
00226     }
00227 }
00228 
00229 void FileCreatePart::slotNewFilePopup( int pFileType )
00230 {
00231     const FileType* filetype = (const FileType*) pFileType;
00232     slotFiletypeSelected( filetype );
00233 }
00234 
00235 void FileCreatePart::slotNewFile() {
00236   KDevCreateFile::CreatedFile createdFile = createNewFile();
00237   openCreatedFile(createdFile);
00238 }
00239 
00240 void FileCreatePart::slotProjectOpened() {
00241     QTimer::singleShot( 0, this, SLOT(slotInitialize()) );
00242 }
00243 
00244 void FileCreatePart::addFileType(const QString & filename) {
00245   FileType * filetype = getType(filename);
00246   if (!filetype) {
00247     filetype = new FileType;
00248     filetype->setName( filename + " files" );
00249     filetype->setExt( filename );
00250     filetype->setCreateMethod("template");
00251     m_filetypes.append(filetype);
00252   }
00253   filetype->setEnabled(true);
00254 }
00255 
00256 void FileCreatePart::slotProjectClosed() {
00257   m_filetypes.clear();
00258   refresh();
00259   QTimer::singleShot( 0, this, SLOT(slotGlobalInitialize()) );
00260 }
00261 
00262 void FileCreatePart::slotFiletypeSelected(const FileType * filetype) {
00263 
00264   KDevCreateFile::CreatedFile createdFile = createNewFile(filetype->ext(),
00265                                                           QString::null,
00266                                                           QString::null,
00267                                                           filetype->subtypeRef());
00268 
00269   if (project())
00270     openCreatedFile(createdFile);
00271 
00272 //  mainWindow()->lowerView( typeChooserWidgetAsQWidget() );
00273 }
00274 
00275 void FileCreatePart::openCreatedFile(const KDevCreateFile::CreatedFile & createdFile) {
00276     if (createdFile.status == KDevCreateFile::CreatedFile::STATUS_OK && project() ) {
00277     KURL uu(project()->projectDirectory() + createdFile.dir + "/" + createdFile.filename );
00278     partController()->editDocument ( uu );
00279   }
00280 }
00281 
00282 int FileCreatePart::readTypes(const QDomDocument & dom, QPtrList<FileType> &m_filetypes, bool enable) {
00283   int numRead = 0;
00284   QDomElement fileTypes = DomUtil::elementByPath(dom,"/kdevfilecreate/filetypes");
00285   if (!fileTypes.isNull()) {
00286     for(QDomNode node = fileTypes.firstChild();!node.isNull();node=node.nextSibling()) {
00287 //      kapp->processEvents();
00288 
00289       if (node.isElement() && node.nodeName()=="type") {
00290         QDomElement element = node.toElement();
00291         FileType * filetype = new FileType;
00292         filetype->setName( element.attribute("name") );
00293         filetype->setExt( element.attribute("ext") );
00294         filetype->setCreateMethod( element.attribute("create") );
00295 
00296         filetype->setIcon( element.attribute("icon") );
00297         filetype->setDescr( (DomUtil::namedChildElement(element, "descr")).text() );
00298         filetype->setEnabled(enable || (filetype->ext()==""));
00299         m_filetypes.append(filetype);
00300         numRead++;
00301 
00302         kdDebug(9034) << "node: " << filetype->name().latin1() << endl;
00303 
00304         if (node.hasChildNodes()) {
00305           for(QDomNode subnode = node.firstChild();!subnode.isNull();subnode=subnode.nextSibling()) {
00306             kdDebug(9034) << "subnode: " << subnode.nodeName().latin1() << endl;
00307 //            kapp->processEvents();
00308             if (subnode.isElement() && subnode.nodeName()=="subtype") {
00309               QDomElement subelement = subnode.toElement();
00310               FileType * subtype = new FileType;
00311               subtype->setExt( filetype->ext() );
00312               subtype->setCreateMethod( filetype->createMethod() );
00313               subtype->setSubtypeRef( subelement.attribute("ref") );
00314               subtype->setIcon( subelement.attribute("icon") );
00315               subtype->setName( subelement.attribute("name") );
00316               subtype->setDescr( (DomUtil::namedChildElement(subelement, "descr")).text() );
00317               subtype->setEnabled(enable);
00318               filetype->addSubtype(subtype);
00319             }
00320           }
00321         }
00322       }
00323     }
00324   }
00325   return numRead;
00326 }
00327 
00328 FileType * FileCreatePart::getType(const QString & ex, const QString subtRef) {
00329 
00330   QString subtypeRef = subtRef;
00331   QString ext = ex;
00332   int dashPos = ext.find('-');
00333   if (dashPos>-1 && subtRef.isNull()) {
00334     ext = ex.left(dashPos);
00335     subtypeRef = ex.mid(dashPos+1);
00336   }
00337 
00338   QPtrList<FileType> filetypes = getFileTypes();
00339   for(FileType * filetype = filetypes.first();
00340       filetype;
00341       filetype=filetypes.next()) {
00342     if (filetype->ext()==ext) {
00343       if (subtypeRef.isNull()) return filetype;
00344       QPtrList<FileType> subtypes = filetype->subtypes();
00345       for(FileType * subtype = subtypes.first();
00346           subtype;
00347           subtype=subtypes.next()) {
00348         if (subtypeRef==subtype->subtypeRef()) return subtype;
00349       }
00350     }
00351   }
00352   return NULL;
00353 }
00354 
00355 FileType * FileCreatePart::getEnabledType(const QString & ex, const QString subtRef) {
00356 
00357   QString subtypeRef = subtRef;
00358   QString ext = ex;
00359   int dashPos = ext.find('-');
00360   if (dashPos>-1 && subtRef.isNull()) {
00361     ext = ex.left(dashPos);
00362     subtypeRef = ex.mid(dashPos+1);
00363   }
00364 
00365   QPtrList<FileType> filetypes = getFileTypes();
00366   for(FileType * filetype = filetypes.first();
00367       filetype;
00368       filetype=filetypes.next()) {
00369     if (filetype->ext()==ext) {
00370       if ( (subtypeRef.isNull()) && (filetype->enabled()) ) return filetype;
00371       QPtrList<FileType> subtypes = filetype->subtypes();
00372       for(FileType * subtype = subtypes.first();
00373           subtype;
00374           subtype=subtypes.next()) {
00375         if ( (subtypeRef==subtype->subtypeRef()) && (filetype->enabled()) ) return subtype;
00376       }
00377     }
00378   }
00379   return NULL;
00380 }
00381 
00382 // KDevFileCreate interface
00383 
00384 KDevCreateFile::CreatedFile FileCreatePart::createNewFile(QString ext, QString dir, QString name, QString subtype)
00385 {
00386   KDevCreateFile::CreatedFile result;
00387   
00388   KURL projectURL;
00389   if ( !project() )
00390   {
00391     //result.status = KDevCreateFile::CreatedFile::STATUS_NOTCREATED;
00392     //return result;
00393   }
00394   else
00395   {
00396     projectURL = project()->projectDirectory();
00397   }
00398 
00399   KURL selectedURL;
00400 
00401   NewFileChooser dialog;
00402   dialog.setFileTypes(m_filetypes);
00403   const FileType *filetype = getEnabledType(ext,subtype);
00404   kdDebug(9034) << "Looking for filetype pointer for " << ext << "/" << subtype << endl;
00405   if (filetype) {
00406     kdDebug(9034) << "found filetype" << endl;
00407   } else {
00408     kdDebug(9034) << "could not find filetype" << endl;
00409   }
00410   if (!project())
00411     dialog.setInProjectMode(false);
00412 
00413   if (!dir.isNull())
00414     dialog.setDirectory(dir);
00415   else if (!project())
00416     dialog.setDirectory(QDir::currentDirPath());
00417   else
00418   {
00419     QString activeDir = project()->activeDirectory();
00420     dialog.setDirectory( project()->projectDirectory() +
00421         ( activeDir[0] == '/' ? "" : "/" )
00422         + activeDir );
00423   }
00424   if (!name.isNull()) dialog.setName(name);
00425   if (filetype) dialog.setCurrent(filetype);
00426 
00427   int dialogResult = dialog.exec();
00428 
00429   if (dialogResult == KDialogBase::Rejected) {
00430     result.status = KDevCreateFile::CreatedFile::STATUS_NOTCREATED;
00431     return result;
00432   }
00433 
00434   // OK was pressed
00435 
00436   result.addToProject = dialog.addToProject();
00437   selectedURL = dialog.url();
00438   const FileType *selectedFileType = dialog.selectedType();
00439 
00440   if (dialog.addToProject() && !projectURL.isParentOf(selectedURL)) {
00441     result.status = KDevCreateFile::CreatedFile::STATUS_NOTWITHINPROJECT;
00442     return result;
00443   }
00444 
00445   if (selectedFileType) {
00446     ext = selectedFileType->ext();
00447     subtype = selectedFileType->subtypeRef();
00448   }
00449 
00450   QString fullPath = selectedURL.path();
00451   // add appropriate extension, if not already there
00452   if (!ext.isNull() & ext!="" & !fullPath.endsWith("." + ext)) fullPath+="." + ext;
00453 
00454   QString filename = URLUtil::filename(fullPath);
00455   kdDebug(9034) << "full path = " << fullPath << endl;
00456 
00457   // add in subtype, if specified
00458   if (!subtype.isEmpty())
00459       ext += "-" + subtype;
00460 
00461   // create file from template
00462   if (!FileTemplate::exists(this, ext) ||
00463       !FileTemplate::copy(this, ext, fullPath) ) {
00464       // no template, create a blank file instead
00465       QFile f(fullPath);
00466       f.open( IO_WriteOnly );
00467       f.close();
00468   }
00469   if (dialog.addToProject())
00470   {
00471     // work out the path relative to the project directory
00472 //    QString relToProj = URLUtil::relativePath(projectURL, selectedURL, URLUtil::SLASH_PREFIX );
00473     QString relToProj = URLUtil::relativePath(projectURL.path(), fullPath, URLUtil::SLASH_PREFIX );
00474     project()->addFile(relToProj.mid(1));
00475   }
00476   else
00477   {
00478     KURL url;
00479     url.setPath(fullPath);
00480     partController()->editDocument(url);
00481   }
00482   
00483   QString fileName = URLUtil::filename(fullPath);
00484   kdDebug(9034) << "file name = " << filename << endl;
00485   
00486   result.filename = fileName;
00487   result.dir = URLUtil::directory(fullPath);
00488   result.status = KDevCreateFile::CreatedFile::STATUS_OK;
00489 
00490   return result;
00491 }
00492 
00493 void FileCreatePart::setShowSideTab(bool on) {
00494   selectWidget(on ? 1 : -1 );
00495 }
00496 
00497 void FileCreatePart::slotNoteFiletype(const FileType * filetype) {
00498   kdDebug(9034) << "Noting file type: " << (filetype ? filetype->ext() : QString::fromLatin1("Null") ) << endl;
00499   m_filedialogFiletype = filetype;
00500 }
00501 
00502 void FileCreatePart::slotInitialize( )
00503 {
00504   m_filetypes.clear();
00505   refresh();
00506   
00507   //read global configuration
00508   slotGlobalInitialize();
00509 
00510   // read in which global templates are to be used for this project
00511   QDomElement useGlobalTypes =
00512     DomUtil::elementByPath(*projectDom(),"/kdevfilecreate/useglobaltypes");
00513   for(QDomNode node = useGlobalTypes.firstChild();
00514       !node.isNull();node=node.nextSibling()) {
00515 
00516 //    kapp->processEvents();
00517 
00518     if (node.isElement() && node.nodeName()=="type") {
00519       QDomElement element = node.toElement();
00520       QString ext = element.attribute("ext");
00521       QString subtyperef = element.attribute("subtyperef");
00522       // if an extension has been specified as enabled, ensure it
00523       // and all its subtypes are enabled
00524       if (subtyperef.isNull()) {
00525         FileType * filetype = getType(ext);
00526         if (filetype) {
00527           filetype->setEnabled(true);
00528           if (filetype->subtypes().count())
00529             filetype->setSubtypesEnabled(true);
00530         }
00531       } else {
00532         // if an extension + subtype have been specified, enable
00533         // the subtype and the extension (the 'parent')
00534         FileType * filetype = getType(ext);
00535         FileType * subtype = getType(ext,subtyperef);
00536         if (filetype && subtype) {
00537           filetype->setEnabled(true);
00538           subtype->setEnabled(true);
00539         }
00540       }
00541     }
00542   }
00543 
00544   // read in the list of file types for this project
00545   if ( project() && readTypes( *projectDom(), m_filetypes, true )==0  ) {
00546     // default by scanning the templates directory if no template info
00547     // found in project file
00548     QDir templDir( project()->projectDirectory() + "/templates/" );
00549     if (templDir.exists()) {
00550       templDir.setFilter( QDir::Files );
00551       const QFileInfoList * list = templDir.entryInfoList();
00552       if( list ){
00553         QFileInfoListIterator it( *list );
00554         QFileInfo *fi;
00555         while ( (fi = it.current()) != 0 ) {
00556           addFileType(fi->fileName());
00557           ++it;
00558         }
00559       }
00560     }
00561 /*    else { // it was probably an imported project
00562       // KLUDGE: we need a better way to determine file types
00563       // the current method looks a bit too restrictive
00564       addFileType( "cpp" );
00565       addFileType( "h" );
00566     }*/
00567   }
00568 
00569   setShowSideTab(m_useSideTab);
00570 
00571   // refresh view
00572   refresh();
00573 }
00574 
00575 void FileCreatePart::slotGlobalInitialize( )
00576 {
00577   // read in global template information
00578   QString globalXMLFile = ::locate("data", "kdevfilecreate/template-info.xml");
00579   kdDebug(9034) << "Found global template info info " << globalXMLFile << endl;
00580   QDomDocument globalDom;
00581   if (!globalXMLFile.isNull() &&
00582       DomUtil::openDOMFile(globalDom,globalXMLFile)) {
00583     kdDebug(9034) << "Reading global template info..." << endl;
00584 //    kapp->processEvents();
00585     readTypes(globalDom, m_filetypes, false);
00586 
00587     // use side tab or not?
00589     QDomElement useSideTab = DomUtil::elementByPath(globalDom,"/kdevfilecreate/sidetab");
00590     if (!useSideTab.isNull() && useSideTab.attribute("active")=="no") {
00591         m_useSideTab = false;
00592 
00593         setShowSideTab(m_useSideTab); // not the cleanest thing to do.. but c'mon, look at the rest of this code.. ;)
00594     }
00595   }
00596   
00597   // refresh view
00598   refresh();
00599 }
00600 
00601 #include "filecreate_part.moc"
00602 
00603     // kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off;
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 23 00:03:57 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003