00001
00002
00003
00004
00005
00006
00007
00008
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
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
00101
00102
00103
00104
00105
00106
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
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
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
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
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
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
00392
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
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
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
00458 if (!subtype.isEmpty())
00459 ext += "-" + subtype;
00460
00461
00462 if (!FileTemplate::exists(this, ext) ||
00463 !FileTemplate::copy(this, ext, fullPath) ) {
00464
00465 QFile f(fullPath);
00466 f.open( IO_WriteOnly );
00467 f.close();
00468 }
00469 if (dialog.addToProject())
00470 {
00471
00472
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
00508 slotGlobalInitialize();
00509
00510
00511 QDomElement useGlobalTypes =
00512 DomUtil::elementByPath(*projectDom(),"/kdevfilecreate/useglobaltypes");
00513 for(QDomNode node = useGlobalTypes.firstChild();
00514 !node.isNull();node=node.nextSibling()) {
00515
00516
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
00523
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
00533
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
00545 if ( project() && readTypes( *projectDom(), m_filetypes, true )==0 ) {
00546
00547
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
00562
00563
00564
00565
00566
00567 }
00568
00569 setShowSideTab(m_useSideTab);
00570
00571
00572 refresh();
00573 }
00574
00575 void FileCreatePart::slotGlobalInitialize( )
00576 {
00577
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
00585 readTypes(globalDom, m_filetypes, false);
00586
00587
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);
00594 }
00595 }
00596
00597
00598 refresh();
00599 }
00600
00601 #include "filecreate_part.moc"
00602
00603