1
/***************************************************************************
2
* Copyright (C) 2003 by Julian Rockey *
5
* This program is free software; you can redistribute it and/or modify *
6
* it under the terms of the GNU General Public License as published by *
7
* the Free Software Foundation; either version 2 of the License, or *
8
* (at your option) any later version. *
9
***************************************************************************/
10
#include "filecreate_part.h"
12
#include <qwhatsthis.h>
15
#include <qfileinfo.h>
19
#include <kdeversion.h>
20
#include <kiconloader.h>
22
#include <kdevgenericfactory.h>
23
#include <kfiledialog.h>
25
#include <kstandarddirs.h>
26
#include <kstdaction.h>
28
#include <kapplication.h>
29
#include <kactionclasses.h>
30
#include <kpopupmenu.h>
31
#include <kmessagebox.h>
34
#include "kdevmainwindow.h"
35
#include "kdevproject.h"
36
#include "kdevpartcontroller.h"
37
#include "configwidgetproxy.h"
39
#include "filetemplate.h"
43
#include "filecreate_widget2.h"
44
#include "filecreate_widget3.h"
45
#include "filecreate_filetype.h"
46
#include "filecreate_filedialog.h"
47
#include "filecreate_newfile.h"
48
#include "fcconfigwidget.h"
50
#define PROJECTSETTINGSPAGE 1
51
#define GLOBALSETTINGSPAGE 2
53
#include "kdevplugininfo.h"
57
static const KDevPluginInfo data("kdevfilecreate");
59
typedef KDevGenericFactory<FileCreatePart> FileCreateFactory;
60
K_EXPORT_COMPONENT_FACTORY( libkdevfilecreate, FileCreateFactory( data ) )
62
using namespace FileCreate;
64
FileCreatePart::FileCreatePart(QObject *parent, const char *name, const QStringList & )
65
// : KDevCreateFile(&data, parent, name ? name : "FileCreatePart"), m_selectedWidget(-1), m_useSideTab(true), m_subPopups(0)
66
: KDevCreateFile(&data, parent, name ? name : "FileCreatePart"), m_subPopups(0)
68
setInstance(FileCreateFactory::instance());
69
setXMLFile("kdevpart_filecreate.rc");
71
connect( core(), SIGNAL(projectOpened()), this, SLOT(slotProjectOpened()) );
72
connect( core(), SIGNAL(projectClosed()), this, SLOT(slotProjectClosed()) );
74
_configProxy = new ConfigWidgetProxy( core() );
75
_configProxy->createProjectConfigPage( i18n("File Templates"), PROJECTSETTINGSPAGE, info()->icon() );
76
_configProxy->createGlobalConfigPage( i18n("File Templates"), GLOBALSETTINGSPAGE, info()->icon() );
77
connect( _configProxy, SIGNAL(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )),
78
this, SLOT(insertConfigWidget(const KDialogBase*, QWidget*, unsigned int )) );
81
KToolBarPopupAction * newAction = new KToolBarPopupAction( i18n("&New"), "filenew", CTRL+Qt::Key_N, this, SLOT(slotNewFile()), actionCollection(), "file_new");
82
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.") );
83
newAction->setToolTip( i18n("Create a new file") );
84
m_newPopupMenu = newAction->popupMenu();
85
connect(m_newPopupMenu, SIGNAL(aboutToShow()), this, SLOT(slotAboutToShowNewPopupMenu()));
87
QTimer::singleShot( 0, this, SLOT(slotGlobalInitialize()) );
91
FileCreatePart::~FileCreatePart()
95
m_newPopupMenu->clear();
99
void FileCreatePart::insertConfigWidget( const KDialogBase * dlg, QWidget * page, unsigned int pagenumber )
101
kdDebug() << k_funcinfo << endl;
105
case PROJECTSETTINGSPAGE:
107
FCConfigWidget* w = new FCConfigWidget( this, false, page, "filecreate config widget" );
108
connect( dlg, SIGNAL( okClicked( ) ), w, SLOT( accept( ) ) );
112
case GLOBALSETTINGSPAGE:
114
FCConfigWidget *w = new FCConfigWidget( this, true, page, "filecreate config widget" );
115
connect(dlg, SIGNAL(okClicked()), w, SLOT(accept()));
121
void FileCreatePart::slotAboutToShowNewPopupMenu()
123
KIconLoader * m_iconLoader = KGlobal::iconLoader();
124
m_newPopupMenu->clear();
128
FileType * filetype = m_filetypes.first();
129
for(; filetype; filetype=m_filetypes.next())
131
if (filetype->enabled())
133
if (filetype->subtypes().count()==0)
135
QPixmap iconPix = m_iconLoader->loadIcon(
136
filetype->icon(), KIcon::Desktop, KIcon::SizeSmall,
137
KIcon::DefaultState, NULL, true);
138
m_newPopupMenu->insertItem(iconPix, filetype->name(), this,
139
SLOT(slotNewFilePopup(int)), 0, ++id );
140
m_newPopupMenu->setItemParameter( id, (long)filetype );
143
KPopupMenu* subMenu = NULL;
144
QPtrList<FileType> subtypes = filetype->subtypes();
145
for(FileType * subtype = subtypes.first(); subtype; subtype=subtypes.next())
147
if (subtype->enabled()){
149
subMenu = new KPopupMenu(0,0);
150
QPixmap iconPix = m_iconLoader->loadIcon(
151
subtype->icon(), KIcon::Desktop, KIcon::SizeSmall,
152
KIcon::DefaultState, NULL, true);
153
subMenu->insertItem(iconPix, subtype->name(), this,
154
SLOT(slotNewFilePopup(int)), 0, ++id );
155
subMenu->setItemParameter( id, (long)subtype );
162
m_subPopups = new QPtrList<KPopupMenu>;
163
m_subPopups->setAutoDelete(true);
165
m_subPopups->append( subMenu );
166
m_newPopupMenu->insertItem( filetype->name(), subMenu );
175
void FileCreatePart::slotNewFilePopup( int pFileType )
177
const FileType* filetype = (const FileType*) pFileType;
178
slotFiletypeSelected( filetype );
181
void FileCreatePart::slotNewFile() {
182
KDevCreateFile::CreatedFile createdFile = createNewFile();
183
if (createdFile.status == KDevCreateFile::CreatedFile::STATUS_NOTCREATED)
184
KMessageBox::error(0, i18n("Cannot create file. Check whether the directory and filename are valid."));
185
else if (createdFile.status != KDevCreateFile::CreatedFile::STATUS_CANCELED)
186
openCreatedFile(createdFile);
189
void FileCreatePart::slotProjectOpened() {
190
QTimer::singleShot( 0, this, SLOT(slotInitialize()) );
193
void FileCreatePart::addFileType(const QString & filename) {
194
FileType * filetype = getType(filename);
196
filetype = new FileType;
197
filetype->setName( filename + " files" );
198
filetype->setExt( filename );
199
filetype->setCreateMethod("template");
200
m_filetypes.append(filetype);
202
filetype->setEnabled(true);
205
void FileCreatePart::slotProjectClosed() {
207
QTimer::singleShot( 0, this, SLOT(slotGlobalInitialize()) );
210
void FileCreatePart::slotFiletypeSelected(const FileType * filetype) {
212
KDevCreateFile::CreatedFile createdFile = createNewFile(filetype->ext(),
215
filetype->subtypeRef());
217
openCreatedFile(createdFile);
220
void FileCreatePart::openCreatedFile(const KDevCreateFile::CreatedFile & createdFile)
222
if ( createdFile.status == KDevCreateFile::CreatedFile::STATUS_OK )
224
KURL uu( createdFile.dir + "/" + createdFile.filename );
225
partController()->editDocument ( uu );
229
int FileCreatePart::readTypes(const QDomDocument & dom, QPtrList<FileType> &m_filetypes, bool enable) {
231
QDomElement fileTypes = DomUtil::elementByPath(dom,"/kdevfilecreate/filetypes");
232
if (!fileTypes.isNull()) {
233
for(QDomNode node = fileTypes.firstChild();!node.isNull();node=node.nextSibling()) {
235
if (node.isElement() && node.nodeName()=="type") {
236
QDomElement element = node.toElement();
237
FileType * filetype = new FileType;
238
filetype->setName( element.attribute("name") );
239
filetype->setExt( element.attribute("ext") );
240
filetype->setCreateMethod( element.attribute("create") );
242
filetype->setIcon( element.attribute("icon") );
243
filetype->setDescr( (DomUtil::namedChildElement(element, "descr")).text() );
244
filetype->setEnabled(enable || (filetype->ext()==""));
245
m_filetypes.append(filetype);
248
kdDebug(9034) << "node: " << filetype->name().latin1() << endl;
250
if (node.hasChildNodes()) {
251
for(QDomNode subnode = node.firstChild();!subnode.isNull();subnode=subnode.nextSibling()) {
252
kdDebug(9034) << "subnode: " << subnode.nodeName().latin1() << endl;
253
if (subnode.isElement() && subnode.nodeName()=="subtype") {
254
QDomElement subelement = subnode.toElement();
255
FileType * subtype = new FileType;
256
subtype->setExt( filetype->ext() );
257
subtype->setCreateMethod( filetype->createMethod() );
258
subtype->setSubtypeRef( subelement.attribute("ref") );
259
subtype->setIcon( subelement.attribute("icon") );
260
subtype->setName( subelement.attribute("name") );
261
subtype->setDescr( (DomUtil::namedChildElement(subelement, "descr")).text() );
262
subtype->setEnabled(enable);
263
filetype->addSubtype(subtype);
273
FileType * FileCreatePart::getType(const QString & ex, const QString subtRef) {
275
QString subtypeRef = subtRef;
277
int dashPos = ext.find('-');
278
if (dashPos>-1 && subtRef.isNull()) {
279
ext = ex.left(dashPos);
280
subtypeRef = ex.mid(dashPos+1);
283
QPtrList<FileType> filetypes = getFileTypes();
284
for(FileType * filetype = filetypes.first();
286
filetype=filetypes.next()) {
287
if (filetype->ext()==ext) {
288
if (subtypeRef.isNull()) return filetype;
289
QPtrList<FileType> subtypes = filetype->subtypes();
290
for(FileType * subtype = subtypes.first();
292
subtype=subtypes.next()) {
293
if (subtypeRef==subtype->subtypeRef()) return subtype;
300
FileType * FileCreatePart::getEnabledType(const QString & ex, const QString subtRef) {
302
QString subtypeRef = subtRef;
304
int dashPos = ext.find('-');
305
if (dashPos>-1 && subtRef.isNull()) {
306
ext = ex.left(dashPos);
307
subtypeRef = ex.mid(dashPos+1);
310
QPtrList<FileType> filetypes = getFileTypes();
311
for(FileType * filetype = filetypes.first();
313
filetype=filetypes.next()) {
314
if (filetype->ext()==ext) {
315
if ( (subtypeRef.isNull()) && (filetype->enabled()) ) return filetype;
316
QPtrList<FileType> subtypes = filetype->subtypes();
317
for(FileType * subtype = subtypes.first();
319
subtype=subtypes.next()) {
320
if ( (subtypeRef==subtype->subtypeRef()) && (filetype->enabled()) ) return subtype;
327
// KDevFileCreate interface
329
KDevCreateFile::CreatedFile FileCreatePart::createNewFile(QString ext, QString dir, QString name, QString subtype)
331
KDevCreateFile::CreatedFile result;
336
//result.status = KDevCreateFile::CreatedFile::STATUS_NOTCREATED;
341
projectURL = project()->projectDirectory();
346
NewFileChooser dialog;
347
dialog.setFileTypes(m_filetypes);
348
const FileType *filetype = getEnabledType(ext,subtype);
349
kdDebug(9034) << "Looking for filetype pointer for " << ext << "/" << subtype << endl;
351
kdDebug(9034) << "found filetype" << endl;
353
kdDebug(9034) << "could not find filetype" << endl;
356
dialog.setInProjectMode(false);
359
dialog.setDirectory(dir);
361
dialog.setDirectory(QDir::currentDirPath());
364
QString activeDir = project()->activeDirectory();
365
dialog.setDirectory( project()->projectDirectory() +
366
( activeDir[0] == '/' ? "" : "/" )
369
if (!name.isNull()) dialog.setName(name);
370
if (filetype) dialog.setCurrent(filetype);
372
dialog.setInitialSize(QSize(500, 200));
373
int dialogResult = dialog.exec();
375
if (dialogResult == KDialogBase::Rejected) {
376
result.status = KDevCreateFile::CreatedFile::STATUS_CANCELED;
382
result.addToProject = dialog.addToProject();
383
selectedURL = dialog.url();
384
const FileType *selectedFileType = dialog.selectedType();
386
if (dialog.addToProject() && !projectURL.isParentOf(selectedURL) && !(project()->options() & KDevProject::UsesQMakeBuildSystem) ) {
387
result.status = KDevCreateFile::CreatedFile::STATUS_NOTWITHINPROJECT;
391
if (selectedFileType) {
392
ext = selectedFileType->ext();
393
subtype = selectedFileType->subtypeRef();
396
QString fullPath = selectedURL.path();
397
// add appropriate extension, if not already there
398
if ( !ext.isEmpty() && !fullPath.endsWith("." + ext)) fullPath+="." + ext;
400
QString filename = URLUtil::filename(fullPath);
401
kdDebug(9034) << "full path = " << fullPath << endl;
403
// add in subtype, if specified
404
if (!subtype.isEmpty())
405
ext += "-" + subtype;
407
// create file from template
408
bool created = false;
409
if (FileTemplate::exists(this, ext))
410
created = FileTemplate::copy(this, ext, fullPath);
412
// no template, create a blank file instead
414
created = f.open( IO_WriteOnly );
419
result.status = KDevCreateFile::CreatedFile::STATUS_NOTCREATED;
423
if (dialog.addToProject())
425
// work out the path relative to the project directory
426
// QString relToProj = URLUtil::relativePath(projectURL, selectedURL, URLUtil::SLASH_PREFIX );
428
if( project()->options() & KDevProject::UsesQMakeBuildSystem )
430
relToProj = URLUtil::relativePathToFile( project()->projectDirectory(), fullPath );
431
project()->addFile(relToProj);
434
relToProj = URLUtil::relativePath(projectURL.path(), fullPath, URLUtil::SLASH_PREFIX );
435
project()->addFile(relToProj.mid(1));
440
url.setPath(fullPath);
441
partController()->editDocument(url);
443
QString fileName = URLUtil::filename(fullPath);
444
kdDebug(9034) << "file name = " << filename << endl;
446
result.filename = fileName;
447
result.dir = URLUtil::directory(fullPath);
448
result.status = KDevCreateFile::CreatedFile::STATUS_OK;
453
void FileCreatePart::slotNoteFiletype(const FileType * filetype) {
454
kdDebug(9034) << "Noting file type: " << (filetype ? filetype->ext() : QString::fromLatin1("Null") ) << endl;
455
m_filedialogFiletype = filetype;
458
void FileCreatePart::slotInitialize( )
462
//read global configuration
463
slotGlobalInitialize();
465
// read in which global templates are to be used for this project
466
QDomElement useGlobalTypes =
467
DomUtil::elementByPath(*projectDom(),"/kdevfilecreate/useglobaltypes");
468
for(QDomNode node = useGlobalTypes.firstChild();
469
!node.isNull();node=node.nextSibling()) {
471
if (node.isElement() && node.nodeName()=="type") {
472
QDomElement element = node.toElement();
473
QString ext = element.attribute("ext");
474
QString subtyperef = element.attribute("subtyperef");
475
// if an extension has been specified as enabled, ensure it
476
// and all its subtypes are enabled
477
if (subtyperef.isNull()) {
478
FileType * filetype = getType(ext);
480
filetype->setEnabled(true);
481
if (filetype->subtypes().count())
482
filetype->setSubtypesEnabled(true);
485
// if an extension + subtype have been specified, enable
486
// the subtype and the extension (the 'parent')
487
FileType * filetype = getType(ext);
488
FileType * subtype = getType(ext,subtyperef);
489
if (filetype && subtype) {
490
filetype->setEnabled(true);
491
subtype->setEnabled(true);
497
// read in the list of file types for this project
498
if ( project() && readTypes( *projectDom(), m_filetypes, true )==0 ) {
499
// default by scanning the templates directory if no template info
500
// found in project file
501
QDir templDir( project()->projectDirectory() + "/templates/" );
502
if (templDir.exists()) {
503
templDir.setFilter( QDir::Files );
504
const QFileInfoList * list = templDir.entryInfoList();
506
QFileInfoListIterator it( *list );
508
while ( (fi = it.current()) != 0 ) {
509
addFileType(fi->fileName());
514
/* else { // it was probably an imported project
515
// KLUDGE: we need a better way to determine file types
516
// the current method looks a bit too restrictive
517
addFileType( "cpp" );
523
QString FileCreatePart::findGlobalXMLFile() const
527
QStringList filenames = KGlobal::instance()->dirs()->findAllResources("data", "kdevfilecreate/template-info.xml");
528
for( QStringList::const_iterator it = filenames.begin(); it != filenames.end(); ++it )
530
QDomDocument globalDom;
531
DomUtil::openDOMFile(globalDom,*it);
532
QDomElement e = globalDom.documentElement();
533
if( !e.hasAttribute( "version" ) && e.attribute( "version" ).toInt() < version )
538
version = e.attribute( "version" ).toInt();
545
void FileCreatePart::slotGlobalInitialize( )
547
// read in global template information
548
QString globalXMLFile = findGlobalXMLFile();
549
kdDebug(9034) << "Found global template info info " << globalXMLFile << endl;
550
QDomDocument globalDom;
551
if (!globalXMLFile.isNull() && DomUtil::openDOMFile(globalDom,globalXMLFile))
553
kdDebug(9034) << "Reading global template info..." << endl;
555
readTypes(globalDom, m_filetypes, false);
560
#include "filecreate_part.moc"
562
// kate: indent-width 2; replace-tabs on; tab-width 4; space-indent on;