1
/***************************************************************************
2
* Copyright (C) 2001-2002 by Bernd Gehrmann *
4
* Copyright (C) 2001 by Sandy Meier *
5
* smeier@kdevelop.org *
7
* This program is free software; you can redistribute it and/or modify *
8
* it under the terms of the GNU General Public License as published by *
9
* the Free Software Foundation; either version 2 of the License, or *
10
* (at your option) any later version. *
12
***************************************************************************/
14
#include "appwizarddlg.h"
17
#include <qbuttongroup.h>
18
#include <qcombobox.h>
19
#include <qtabwidget.h>
20
#include <qwidgetstack.h>
22
#include <qfileinfo.h>
26
#include <qmultilineedit.h>
27
#include <qpushbutton.h>
28
#include <qradiobutton.h>
30
#include <qtextstream.h>
31
#include <qtextview.h>
32
#include <qtoolbutton.h>
34
#include <qvalidator.h>
35
#include <klistview.h>
36
#include <kiconview.h>
40
#include <kglobalsettings.h>
42
#include <kmessagebox.h>
44
#include <kstandarddirs.h>
45
#include <ktempfile.h>
46
#include <kiconloader.h>
47
#include <kfiledialog.h>
49
#include <kapplication.h>
50
#include <kpopupmenu.h>
53
#include <kparts/componentfactory.h>
54
#include <kio/netaccess.h>
56
#include <kmacroexpander.h>
60
#include <kfileitem.h>
61
#include <kio/chmodjob.h>
66
#include "kdevversioncontrol.h"
67
#include "kdevmakefrontend.h"
68
#include "kdevpartcontroller.h"
69
#include "kdevappfrontend.h"
70
#include "kdevplugininfo.h"
71
#include "kdevlicense.h"
73
#include "appwizardfactory.h"
74
#include "appwizardpart.h"
75
#include "filepropspage.h"
77
#include "profilesupport.h"
78
#include "filetemplate.h"
80
#include "propeditor/property.h"
81
#include "propeditor/multiproperty.h"
82
#include "propeditor/propertylist.h"
83
#include "propeditor/propertyeditor.h"
85
AppWizardDialog::AppWizardDialog(AppWizardPart *part, QWidget *parent, const char *name)
86
: AppWizardDialogBase(parent, name,true), m_pCurrentAppInfo(0),
87
m_profileSupport(new ProfileSupport(part))
89
kdDebug( 9000 ) << " ** AppWizardDialog::AppWizardDialog()" << endl;
93
connect( this, SIGNAL( selected( const QString & ) ), this, SLOT( pageChanged() ) );
96
templates_listview->header()->hide();
97
templates_listview->setColumnWidthMode(0, QListView::Maximum); //to provide horiz scrollbar.
99
m_templatesMenu = new KPopupMenu(templates_listview);
100
m_templatesMenu->insertItem(i18n("&Add to Favorites"), this, SLOT(addTemplateToFavourites()));
102
m_favouritesMenu = new KPopupMenu(favourites_iconview);
103
m_favouritesMenu->insertItem(i18n("&Remove Favorite"), this, SLOT(removeFavourite()));
107
m_projectLocationWasChanged=false;
108
m_appsInfo.setAutoDelete(true);
109
m_tempFiles.setAutoDelete(true);
111
KConfig *config = kapp->config();
113
//config->setGroup("AppWizard");
114
//templates_tabwidget->setCurrentPage(config->readNumEntry("CurrentTab", 0));
116
config->setGroup("General Options");
117
QString defaultProjectsDir = config->readPathEntry("DefaultProjectsDir", QDir::homeDirPath()+"/");
119
KStandardDirs *dirs = AppWizardFactory::instance()->dirs();
120
QStringList m_templateNames = dirs->findAllResources("apptemplates", QString::null, false, true);
122
kdDebug(9010) << "Templates: " << endl;
123
QStringList categories;
125
QStringList::Iterator it;
126
for (it = m_templateNames.begin(); it != m_templateNames.end(); ++it) {
127
kdDebug(9010) << (*it) << endl;
129
ApplicationInfo *info = new ApplicationInfo;
130
info->propValues = new PropertyLib::PropertyList();
131
info->templateFile = KGlobal::dirs()->findResource("apptemplates", *it);
132
info->templateName = (*it);
134
KConfig templateConfig(info->templateFile);
135
templateConfig.setGroup("General");
137
info->name = templateConfig.readEntry("Name");
138
info->icon = templateConfig.readEntry("Icon");
139
info->comment = templateConfig.readEntry("Comment");
140
info->fileTemplates = templateConfig.readEntry("FileTemplates");
141
info->openFilesAfterGeneration = templateConfig.readListEntry("ShowFilesAfterGeneration");
142
QString destDir = templateConfig.readPathEntry("DefaultDestinatonDir", defaultProjectsDir);
143
destDir.replace(QRegExp("HOMEDIR"), QDir::homeDirPath());
144
info->defaultDestDir = destDir;
145
QString category = templateConfig.readEntry("Category");
146
// format category to a unique status
147
if (category.right(1) == "/")
148
category.remove(category.length()-1, 1); // remove /
149
if (category.left(1) != "/")
150
category.prepend("/"); // prepend /
151
categories.append(category);
152
info->category = category;
153
info->sourceArchive = templateConfig.readEntry("Archive");
155
// Grab includes list
156
QStringList groups = templateConfig.groupList();
157
groups.remove("General");
158
QStringList::Iterator group = groups.begin();
159
for( ; group != groups.end(); ++group)
161
templateConfig.setGroup( (*group) );
162
QString type = templateConfig.readEntry("Type").lower();
163
if( type == "include" ) // Add value
165
info->includes.append( templateConfig.readEntry( "File" ) );
166
kdDebug(9010) << "Adding: " << templateConfig.readEntry( "File" ) << endl;
170
// Build builtins map to bootstrap.
171
QString source = kdevRoot( info->templateName );
172
info->subMap.insert("kdevelop", source );
174
// Add includes to the main template...
175
QStringList::Iterator include = info->includes.begin();
176
for( ; include != info->includes.end(); ++include)
178
if( !(*include).isEmpty() )
180
QString file = KMacroExpander::expandMacros( ( *include ), info->subMap);
181
KConfig tmpCfg( file );
182
tmpCfg.copyTo( "", &templateConfig);
183
kdDebug(9010) << "Merging: " << tmpCfg.name() << endl;
187
groups = templateConfig.groupList(); // Must get this again since its changed!
188
group = groups.begin();
189
for( ; group != groups.end(); ++group)
191
templateConfig.setGroup( (*group) );
192
QString type = templateConfig.readEntry("Type", "value").lower();
193
kdDebug(9010) << "Reading " << (*group) << " of type " << type << endl;
194
if( type == "value" ) // Add value
196
QString name = templateConfig.readEntry( "Value" );
197
QString label = templateConfig.readEntry( "Comment" );
198
QString type = templateConfig.readEntry( "ValueType", "String" );
199
QVariant::Type variantType = QVariant::nameToType( type.latin1());
200
QVariant value = templateConfig.readPropertyEntry( "Default", variantType );
201
value.cast( variantType ); // fix this in kdelibs...
202
if( !name.isEmpty() && !label.isEmpty() )
203
info->propValues->addProperty( new PropertyLib::Property( (int)variantType, name, label, value ) );
206
else if( type == "install" ) // copy dir
209
file.source = templateConfig.readPathEntry("Source");
210
file.dest = templateConfig.readPathEntry("Dest");
211
file.process = templateConfig.readBoolEntry("Process",true);
212
file.isXML = templateConfig.readBoolEntry("EscapeXML",false);
213
file.option = templateConfig.readEntry("Option");
214
info->fileList.append(file);
216
else if( type == "install archive" )
219
arch.source = templateConfig.readPathEntry("Source");
220
arch.dest = templateConfig.readPathEntry("Dest");
221
arch.process = templateConfig.readBoolEntry("Process",true);
222
arch.option = templateConfig.readEntry("Option", "" );
223
info->archList.append(arch);
225
else if( type == "mkdir" )
228
dir.dir = templateConfig.readPathEntry("Dir");
229
dir.option = templateConfig.readEntry("Option", "" );
230
dir.perms = templateConfig.readNumEntry("Perms", 0777 );
231
info->dirList.append(dir);
233
else if( type == "finishcmd" )
235
info->finishCmd=templateConfig.readPathEntry("Command");
236
info->finishCmdDir=templateConfig.readPathEntry("Directory");
238
else if( type == "ui")
240
QString name = templateConfig.readPathEntry("File");
241
info->customUI = name;
243
else if( type == "message" )
245
info->message = templateConfig.readEntry( "Comment" );
250
m_appsInfo.append(info);
253
// Insert categories into list view
255
for (it = categories.begin(); it != categories.end(); ++it)
256
insertCategoryIntoTreeView(*it);
258
// Insert items into list view
259
QPtrListIterator<ApplicationInfo> ait(m_appsInfo);
260
for (; ait.current(); ++ait) {
261
QListViewItem *item = m_categoryMap.find(ait.current()->category);
264
item = new KListViewItem(item, ait.current()->name);
265
item->setPixmap(0, SmallIcon("kdevelop"));
268
kdDebug(9010) << "Error can't find category in categoryMap: "
269
<< ait.current()->category << endl;
270
ait.current()->item = item;
273
//Load favourites from config
274
populateFavourites();
276
QString author, email;
277
AppWizardUtil::guessAuthorAndEmail(&author, &email);
278
author_edit->setText(author);
279
email_edit->setText(email);
280
QToolTip::add( dest_edit->button(), i18n("Choose projects directory") );
281
dest_edit->setURL(defaultProjectsDir);
282
dest_edit->setMode(KFile::Directory|KFile::ExistingOnly|KFile::LocalOnly);
286
// addPage(m_sdi_fileprops_page,"Class/File Properties");
290
setNextEnabled(generalPage, false);
292
// QRegExp appname_regexp ("[a-zA-Z][a-zA-Z0-9_]*"); //Non-Unicode version
293
/* appname will start with a letter, and will contain letters,
294
digits or underscores. */
295
QRegExp appname_regexp ("[a-zA-Z][a-zA-Z0-9_]*");
296
// How about names like "__" or "123" for project name? Are they legal?
297
QRegExpValidator *appname_edit_validator;
298
appname_edit_validator = new QRegExpValidator (appname_regexp,
301
appname_edit->setValidator(appname_edit_validator);
303
// insert the licenses into the license_combo
304
QDict< KDevLicense > lics( licenses() );
305
QDictIterator< KDevLicense > dit(lics);
307
for( ; dit.current(); ++dit )
309
license_combo->insertItem( dit.currentKey(), idx++ );
310
if( dit.currentKey() == "GPL" )
311
license_combo->setCurrentItem( idx - 1 );
314
connect( license_combo, SIGNAL(activated(int)), this, SLOT(licenseChanged()) );
316
m_custom_options_layout = new QHBoxLayout( custom_options );
317
m_custom_options_layout->setAutoAdd(true);
319
showTemplates(false);
322
AppWizardDialog::~AppWizardDialog()
325
void AppWizardDialog::loadVcs()
327
m_vcsForm = new VcsForm();
330
m_vcsForm->combo->insertItem( i18n("no version control system", "None"), i );
331
m_vcsForm->stack->addWidget( 0, i++ );
333
// We query for all vcs integrators for KDevelop
334
KTrader::OfferList offers = KTrader::self()->query("KDevelop/VCSIntegrator", "");
335
KTrader::OfferList::const_iterator serviceIt = offers.begin();
336
for (; serviceIt != offers.end(); ++serviceIt)
338
KService::Ptr service = *serviceIt;
339
kdDebug(9010) << "AppWizardDialog::loadVcs: creating vcs integrator "
340
<< service->name() << endl;
342
KLibFactory *factory = KLibLoader::self()->factory(QFile::encodeName(service->library()));
344
QString errorMessage = KLibLoader::self()->lastErrorMessage();
345
kdDebug(9010) << "There was an error loading the module " << service->name() << endl <<
346
"The diagnostics is:" << endl << errorMessage << endl;
350
QObject *obj = factory->create(0, service->name().latin1(),
351
"KDevVCSIntegrator", args);
352
KDevVCSIntegrator *integrator = (KDevVCSIntegrator*) obj;
355
kdDebug(9010) << " failed to create vcs integrator " << service->name() << endl;
358
kdDebug(9010) << " success" << endl;
360
QString vcsName = service->property("X-KDevelop-VCS").toString();
361
m_vcsForm->combo->insertItem(vcsName, i);
362
m_integrators.insert(vcsName, integrator);
364
VCSDialog *vcs = integrator->integrator(m_vcsForm->stack);
367
m_integratorDialogs[i] = vcs;
368
QWidget *w = vcs->self();
370
m_vcsForm->stack->addWidget(w, i++);
372
kdDebug(9010) << " integrator widget is 0" << endl;
375
kdDebug(9010) << " integrator is 0" << endl;
379
addPage(m_vcsForm, i18n("Version Control System"));
382
void AppWizardDialog::updateNextButtons()
384
bool validGeneralPage = m_pCurrentAppInfo
385
&& !appname_edit->text().isEmpty()
387
bool validPropsPage = !version_edit->text().isEmpty()
388
&& !author_edit->text().isEmpty();
390
setFinishEnabled(m_lastPage, validGeneralPage && validPropsPage);
391
nextButton()->setEnabled(
392
currentPage() == generalPage ? validGeneralPage : validPropsPage );
395
void AppWizardDialog::textChanged()
402
void AppWizardDialog::licenseChanged()
404
QValueList<AppWizardFileTemplate>::Iterator it;
405
if( license_combo->currentItem() == 0 )
407
for (it = m_fileTemplates.begin(); it != m_fileTemplates.end(); ++it)
409
QMultiLineEdit *edit = (*it).edit;
410
edit->setText( QString::null );
413
KDevLicense* lic = licenses()[ license_combo->currentText() ];
414
for (it = m_fileTemplates.begin(); it != m_fileTemplates.end(); ++it) {
415
QString style = (*it).style;
416
QMultiLineEdit *edit = (*it).edit;
418
KDevFile::CommentingStyle commentStyle = KDevFile::CPPStyle;
419
if (style == "PStyle") {
420
commentStyle = KDevFile::PascalStyle;
421
} else if (style == "AdaStyle") {
422
commentStyle = KDevFile::AdaStyle;
423
} else if (style == "ShellStyle") {
424
commentStyle = KDevFile::BashStyle;
425
} else if (style == "XMLStyle") {
426
commentStyle = KDevFile::XMLStyle;
430
text = lic->assemble( commentStyle, author_edit->text(), email_edit->text() , 0 );
436
QString AppWizardDialog::kdevRoot(const QString &templateName ) const
439
QFileInfo finfo(templateName);
440
QDir dir(finfo.dir());
442
return dir.absPath();
445
void AppWizardDialog::accept()
447
QFileInfo fi(finalLoc_label->text());
448
// check /again/ whether the dir already exists; maybe users create it in the meantime
450
KMessageBox::sorry(this, i18n("The directory you have chosen as the location for "
451
"the project already exists."));
452
showPage(generalPage);
453
appname_edit->setFocus();
454
projectLocationChanged();
458
QString source = kdevRoot( m_pCurrentAppInfo->templateName );
460
// Unpack template archive to temp dir, and get the name
463
archDir.setAutoDelete(true);
464
KTar templateArchive( source + "/" + m_pCurrentAppInfo->sourceArchive, "application/x-gzip" );
465
if( templateArchive.open( IO_ReadOnly ) )
467
//templateArchive.directory()->copyTo(archDir.name(), true);
468
unpackArchive(templateArchive.directory(), archDir.name(), false);
472
KMessageBox::sorry(this, i18n("The template %1 cannot be opened.").arg( source + "/" + m_pCurrentAppInfo->sourceArchive ) );
473
templateArchive.close();
476
templateArchive.close();
478
// Build KMacroExpander map
479
//m_customOptions->dataForm()->fillPropertyMap(&m_pCurrentAppInfo->subMap);
480
PropertyLib::PropertyList::Iterator idx = m_pCurrentAppInfo->propValues->begin();
481
for( ; idx != m_pCurrentAppInfo->propValues->end(); ++idx)
482
m_pCurrentAppInfo->subMap.insert( idx.data()->name(), idx.data()->value().toString() );
484
m_pCurrentAppInfo->subMap.insert("src", archDir.name() );
485
m_pCurrentAppInfo->subMap.insert("dest", finalLoc_label->text() );
486
m_pCurrentAppInfo->subMap.insert("APPNAME", appname_edit->text() );
487
m_pCurrentAppInfo->subMap.insert("APPNAMELC", appname_edit->text().lower() );
488
m_pCurrentAppInfo->subMap.insert("APPNAMESC", QString(appname_edit->text()[0]).upper() + appname_edit->text().mid(1));
489
m_pCurrentAppInfo->subMap.insert("APPNAMEUC", appname_edit->text().upper() );
490
m_pCurrentAppInfo->subMap.insert("AUTHOR", author_edit->text() );
491
m_pCurrentAppInfo->subMap.insert("EMAIL", email_edit->text() );
492
m_pCurrentAppInfo->subMap.insert("VERSION", version_edit->text());
493
m_pCurrentAppInfo->subMap.insert( "I18N", "i18n" );
494
m_pCurrentAppInfo->subMap.insert("YEAR", QString::number( QDate::currentDate().year() ) );
496
// This isn't too pretty, but we have several templates that use KAboutData::License_${LICENSE}
497
// and unsurprisingly, KAboutData doesn't cover every imaginable case.
498
// These are the licenses known to KDE-3.2 KAboutData, KDevelop doesn't have all of these as prepared options today
499
QString license = license_combo->currentText();
500
if ( license == "GPL" || license == "GPL_V2" || license == "LGPL" || license == "LGPL_V2"||
501
license == "BSD" || license == "Artistic" || license == "QPL" || license == "QPL_V1_0" )
503
m_pCurrentAppInfo->subMap.insert("LICENSE", license );
507
m_pCurrentAppInfo->subMap.insert("LICENSE", "Custom" );
511
QStringList cleanUpSubstMap;
512
cleanUpSubstMap << "src" << "I18N" << "kdevelop";
514
// Add template files to the fileList
515
installDir templateDir;
516
templateDir.dir = "%{dest}/templates";
517
m_pCurrentAppInfo->dirList.prepend(templateDir);
520
baseDir.dir = "%{dest}";
521
m_pCurrentAppInfo->dirList.prepend( baseDir );
523
// This is too silly for words, but it's either this or reimplementing FileTemplate
524
QString tempProjectDomSource = "<!DOCTYPE kdevelop><kdevelop><general><author>%1</author><email>%2</email><version>%3</version></general></kdevelop>";
525
tempProjectDomSource = tempProjectDomSource.arg( author_edit->text() ).arg( email_edit->text() ).arg( version_edit->text() );
526
QDomDocument tempProjectDom;
527
tempProjectDom.setContent( tempProjectDomSource );
529
QValueList<AppWizardFileTemplate>::Iterator it;
530
for (it = m_fileTemplates.begin(); it != m_fileTemplates.end(); ++it) {
531
KTempFile *tempFile = new KTempFile();
532
m_tempFiles.append(tempFile);
534
QString templateText( FileTemplate::makeSubstitutions( tempProjectDom, (*it).edit->text() ) );
536
f.open(IO_WriteOnly, tempFile->handle());
537
QTextStream temps(&f);
538
temps << templateText;
540
QString templateName( QString( "%1_TEMPLATE" ).arg( (*it).suffix ).upper() );
541
cleanUpSubstMap << templateName;
542
m_pCurrentAppInfo->subMap.insert( templateName, KMacroExpander::expandMacros(templateText , m_pCurrentAppInfo->subMap) );
545
file.source = tempFile->name();
546
file.dest = QString( "%{dest}/templates/%1" ).arg( (*it).suffix );
549
m_pCurrentAppInfo->fileList.append( file );
552
// Add license file to the file list
553
QString licenseFile, licenseName = i18n("Custom");
555
if( license_combo->currentItem() != 0 )
557
licenseName = license_combo->currentText();
558
KDevLicense* lic = licenses()[ licenseName ];
561
QStringList files( lic->copyFiles() );
562
QStringList::Iterator it = files.begin();
563
for( ; it != files.end(); ++it )
566
file.source = QString( "%{kdevelop}/template-common/%1" ).arg( *it );
567
file.dest = QString("%{dest}/%1").arg( *it );
570
m_pCurrentAppInfo->fileList.append( file );
573
m_pCurrentAppInfo->subMap.insert("LICENSEFILE", files.first() );
577
// Run macro expander on both the dir map and file maps
578
QValueList<installFile>::Iterator fileIt = m_pCurrentAppInfo->fileList.begin();
579
for( ; fileIt != m_pCurrentAppInfo->fileList.end(); ++fileIt)
581
(*fileIt).source = KMacroExpander::expandMacros((*fileIt).source , m_pCurrentAppInfo->subMap);
582
(*fileIt).dest = KMacroExpander::expandMacros((*fileIt).dest , m_pCurrentAppInfo->subMap);
585
QValueList<installArchive>::Iterator archIt = m_pCurrentAppInfo->archList.begin();
586
for( ; archIt != m_pCurrentAppInfo->archList.end(); ++archIt)
588
(*archIt).source = KMacroExpander::expandMacros((*archIt).source , m_pCurrentAppInfo->subMap);
589
(*archIt).dest = KMacroExpander::expandMacros((*archIt).dest , m_pCurrentAppInfo->subMap);
592
QValueList<installDir>::Iterator dirIt = m_pCurrentAppInfo->dirList.begin();
593
for( ; dirIt != m_pCurrentAppInfo->dirList.end(); ++dirIt)
595
(*dirIt).dir = KMacroExpander::expandMacros((*dirIt).dir , m_pCurrentAppInfo->subMap);
598
QMap<QString,QString>::Iterator mapIt( m_pCurrentAppInfo->subMap.begin() );
599
for( ; mapIt != m_pCurrentAppInfo->subMap.end(); ++mapIt )
601
QString escaped( mapIt.data() );
602
escaped.replace( "&", "&" );
603
escaped.replace( "<", "<" );
604
escaped.replace( ">", ">" );
605
m_pCurrentAppInfo->subMapXML.insert( mapIt.key(), escaped );
609
dirIt = m_pCurrentAppInfo->dirList.begin();
610
for( ; dirIt != m_pCurrentAppInfo->dirList.end(); ++dirIt)
612
kdDebug( 9000 ) << "Process dir " << (*dirIt).dir << endl;
613
if( m_pCurrentAppInfo->subMap[(*dirIt).option] != "false" )
615
if( ! KIO::NetAccess::mkdir( (*dirIt).dir, this ) )
617
KMessageBox::sorry(this, i18n("The directory %1 cannot be created.").arg( (*dirIt).dir ) );
623
archIt = m_pCurrentAppInfo->archList.begin();
624
for( ; archIt != m_pCurrentAppInfo->archList.end(); ++archIt)
626
if( m_pCurrentAppInfo->subMap[(*archIt).option] != "false" )
628
kdDebug( 9010 ) << "unpacking archive " << (*archIt).source << endl;
629
KTar archive( (*archIt).source, "application/x-gzip" );
630
if( archive.open( IO_ReadOnly ) )
632
unpackArchive( archive.directory(), (*archIt).dest, (*archIt).process );
636
KMessageBox::sorry(this, i18n("The archive %1 cannot be opened.").arg( (*archIt).source ) );
645
// Copy files & Process
646
fileIt = m_pCurrentAppInfo->fileList.begin();
647
for( ; fileIt != m_pCurrentAppInfo->fileList.end(); ++fileIt)
649
kdDebug( 9010 ) << "Process file " << (*fileIt).source << endl;
650
if( m_pCurrentAppInfo->subMap[(*fileIt).option] != "false" )
652
if( !copyFile( *fileIt ) )
654
KMessageBox::sorry(this, i18n("The file %1 cannot be created.").arg( (*fileIt).dest) );
657
setPermissions(*fileIt);
660
// if dir still does not exist
661
if (!fi.dir().exists()) {
662
KMessageBox::sorry(this, i18n("The directory above the chosen location does not exist and cannot be created."));
663
showPage(generalPage);
664
dest_edit->setFocus();
668
// KMessageBox::information(this, KMacroExpander::expandMacros(m_pCurrentAppInfo->message, m_pCurrentAppInfo->subMap));
670
QStringList::Iterator cleanIt = cleanUpSubstMap.begin();
671
for(;cleanIt != cleanUpSubstMap.end(); ++cleanIt )
673
m_pCurrentAppInfo->subMap.remove( *cleanIt );
676
if (!m_pCurrentAppInfo->finishCmd.isEmpty())
677
if (KDevAppFrontend *appFrontend = m_part->extension<KDevAppFrontend>("KDevelop/AppFrontend"))
678
appFrontend->startAppCommand(KMacroExpander::expandMacros(m_pCurrentAppInfo->finishCmdDir, m_pCurrentAppInfo->subMap), KMacroExpander::expandMacros(m_pCurrentAppInfo->finishCmd, m_pCurrentAppInfo->subMap), false);
680
openAfterGeneration();
682
int id = m_vcsForm->stack->id(m_vcsForm->stack->visibleWidget());
685
VCSDialog *vcs = m_integratorDialogs[id];
688
kdDebug(9010) << "vcs integrator dialog is ready" << endl;
692
kdDebug(9010) << "no vcs integrator dialog" << endl;
695
kdDebug(9010) << "vcs integrator wasn't selected" << endl;
700
bool AppWizardDialog::copyFile( const installFile& file )
703
copyFile( file.source, file.dest, file.isXML, file.process );
706
#include <sys/types.h>
707
#include <sys/stat.h>
710
bool AppWizardDialog::copyFile( const QString &source, const QString &dest, bool isXML, bool process )
712
kdDebug( 9010 ) << "Copy: " << source << " to " << dest << endl;
715
// Process the file and save it at the destFile location
716
QFile inputFile( source);
717
QFile outputFile( dest );
719
const QMap<QString,QString> &subMap = isXML ?
720
m_pCurrentAppInfo->subMapXML : m_pCurrentAppInfo->subMap;
721
if( inputFile.open( IO_ReadOnly ) && outputFile.open(IO_WriteOnly) )
723
QTextStream input( &inputFile );
724
QTextStream output( &outputFile );
725
while( !input.atEnd() )
726
output << KMacroExpander::expandMacros(input.readLine(), subMap) << "\n";
727
// Preserve file mode...
729
::fstat( inputFile.handle(), &fmode);
730
::fchmod( outputFile.handle(), fmode.st_mode );
742
// Copy the source file to the destFile.
743
return KIO::NetAccess::copy( source, dest, this );
748
void AppWizardDialog::unpackArchive( const KArchiveDirectory *dir, const QString &dest, bool process )
750
KIO::NetAccess::mkdir( dest , this );
751
kdDebug(9010) << "Dir : " << dir->name() << " at " << dest << endl;
752
QStringList entries = dir->entries();
753
kdDebug(9010) << "Entries : " << entries.join(",") << endl;
757
QStringList::Iterator entry = entries.begin();
758
for( ; entry != entries.end(); ++entry )
761
if( dir->entry( (*entry) )->isDirectory() )
763
const KArchiveDirectory *file = (KArchiveDirectory *)dir->entry( (*entry) );
764
unpackArchive( file , dest + "/" + file->name(), process);
766
else if( dir->entry( (*entry) )->isFile() )
768
const KArchiveFile *file = (KArchiveFile *) dir->entry( (*entry) );
771
file->copyTo( dest );
772
setPermissions(file, dest + "/" + file->name());
776
file->copyTo(tdir.name());
777
// assume that an archive does not contain XML files
778
// ( where should we currently get that info from? )
779
if ( !copyFile( QDir::cleanDirPath(tdir.name()+"/"+file->name()), dest + "/" + file->name(), false, process ) )
781
KMessageBox::sorry(this, i18n("The file %1 cannot be created.").arg( dest) );
784
setPermissions(file, dest + "/" + file->name());
791
void AppWizardDialog::templatesTreeViewClicked(QListViewItem *item)
793
if( m_customOptions )
794
delete m_customOptions;
796
// Delete old file template pages
797
while (!m_fileTemplates.isEmpty()) {
798
QMultiLineEdit *edit = m_fileTemplates.first().edit;
801
m_fileTemplates.remove(m_fileTemplates.begin());
805
ApplicationInfo *info = templateForItem(item);
807
m_pCurrentAppInfo = info;
808
if (!info->icon.isEmpty()) {
809
QFileInfo fi(info->templateName);
813
pm.load(dir.filePath(info->icon));
814
icon_label->setPixmap(pm);
818
desc_textview->setText(info->comment);
819
// dest_edit->setURL(info->defaultDestDir);
820
m_projectLocationWasChanged = false;
821
//projectNameChanged(); // set the dest new
823
// Populate new custom options form
824
m_customOptions = new PropertyLib::PropertyEditor( custom_options );
825
m_customOptions->populateProperties(info->propValues);
828
// Create new file template pages
829
QStringList l = QStringList::split(",", info->fileTemplates);
830
if (l.empty()) //if the app template doesn't show file templates, we need to set another m_lastPage, aleXXX
831
m_lastPage=m_vcsForm;
833
QStringList::ConstIterator it = l.begin();
834
while (it != l.end()) {
835
AppWizardFileTemplate fileTemplate;
836
fileTemplate.suffix = *it;
839
fileTemplate.style = *it;
842
fileTemplate.style = "";
844
QMultiLineEdit *edit = new QMultiLineEdit(this);
845
edit->setWordWrap(QTextEdit::NoWrap);
846
edit->setFont(KGlobalSettings::fixedFont());
849
fileTemplate.edit = edit;
850
addPage(edit, i18n("Template for .%1 Files").arg(fileTemplate.suffix));
851
m_fileTemplates.append(fileTemplate);
853
licenseChanged(); // to populate the template views
854
textChanged(); // update Next button state
859
desc_textview->clear();
860
nextButton()->setEnabled(false);
865
void AppWizardDialog::destButtonClicked(const QString& dir)
869
// set new location as default project dir?
870
KConfig *config = kapp->config();
871
config->setGroup("General Options");
872
QDir defPrjDir( config->readPathEntry("DefaultProjectsDir", QDir::homeDirPath()) );
874
kdDebug(9010) << "DevPrjDir == newdir?: " << defPrjDir.absPath() << " == " << newDir.absPath() << endl;
875
if (defPrjDir != newDir) {
876
if (KMessageBox::questionYesNo(this, i18n("Set default project location to: %1?").arg( newDir.absPath() ),
877
i18n("New Project"), i18n("Set"), i18n("Do Not Set")) == KMessageBox::Yes)
879
config->writePathEntry("DefaultProjectsDir", newDir.absPath() + "/");
887
void AppWizardDialog::projectNameChanged()
889
// Location was already edited by hand => don't change
893
void AppWizardDialog::projectLocationChanged()
895
// Jakob Simon-Gaarde: Got tired of the anoying bug with the appname/location confussion.
896
// This version insures WYSIWYG and checks pathvalidity
897
finalLoc_label->setText(dest_edit->url() + (dest_edit->url().right(1)=="/" ? "":"/") + appname_edit->text().lower());
898
QDir qd(dest_edit->url());
899
QFileInfo fi(dest_edit->url() + "/" + appname_edit->text().lower());
900
if (!qd.exists() || appname_edit->displayText().isEmpty()||fi.exists())
902
if (!fi.exists() || appname_edit->displayText().isEmpty()) {
903
finalLoc_label->setText(finalLoc_label->text() + i18n("invalid location", " (invalid)"));
905
finalLoc_label->setText(finalLoc_label->text() + i18n(" (dir/file already exist)"));
915
void AppWizardDialog::insertCategoryIntoTreeView(const QString &completeCategoryPath)
917
kdDebug(9010) << "TemplateCategory: " << completeCategoryPath << endl;
918
QStringList categories = QStringList::split("/", completeCategoryPath);
919
QString category ="";
920
QListViewItem* pParentItem=0;
922
QStringList::ConstIterator it;
923
for (it = categories.begin(); it != categories.end(); ++it) {
924
category = category + "/" + *it;
925
QListViewItem *item = m_categoryMap.find(category);
926
if (!item) { // not found, create it
928
pParentItem = new KListViewItem(templates_listview,*it);
930
pParentItem = new KListViewItem(pParentItem,*it);
932
pParentItem->setPixmap(0, SmallIcon("folder"));
933
//pParentItem->setOpen(true);
934
kdDebug(9010) << "Category: " << category << endl;
935
m_categoryMap.insert(category,pParentItem);
936
m_categoryItems.append(pParentItem);
944
ApplicationInfo *AppWizardDialog::templateForItem(QListViewItem *item)
946
QPtrListIterator<ApplicationInfo> it(m_appsInfo);
947
for (; it.current(); ++it)
948
if (it.current()->item == item)
954
void AppWizardDialog::openAfterGeneration()
956
QString projectFile( finalLoc_label->text() + "/" + appname_edit->text().lower() + ".kdevelop" );
958
// Read the DOM of the newly created project
959
QFile file( projectFile );
960
if( !file.open( IO_ReadOnly ) )
962
QDomDocument projectDOM;
964
int errorLine, errorCol;
966
bool success = projectDOM.setContent( &file, &errorMsg, &errorLine, &errorCol);
970
KMessageBox::sorry( 0, i18n("This is not a valid project file.\n"
971
"XML error in line %1, column %2:\n%3")
972
.arg(errorLine).arg(errorCol).arg(errorMsg));
976
// DOM Modifications go here
977
DomUtil::writeMapEntry( projectDOM, "substmap", m_pCurrentAppInfo->subMap );
979
//save the selected vcs
980
KTrader::OfferList offers = KTrader::self()->query("KDevelop/VCSIntegrator", QString("[X-KDevelop-VCS]=='%1'").arg(m_vcsForm->combo->currentText()));
981
if (offers.count() == 1)
983
KService::Ptr service = offers.first();
984
DomUtil::writeEntry(projectDOM, "/general/versioncontrol", service->property("X-KDevelop-VCSPlugin").toString());
988
KConfig * config = kapp->config();
989
config->setGroup("IgnorePerDefault");
990
QStringList ignoreparts = config->readListEntry( "KDevelop" );
991
DomUtil::writeListEntry( projectDOM, "/general/ignoreparts", "part", ignoreparts );
994
//FIXME PROFILES!!!!!!!!
995
//BEGIN Plugin Profile
997
/* QString category = m_pCurrentAppInfo->category;
998
if ( category.left( 1 ) == "/" )
1000
category = category.right( category.length() -1 );
1003
QString profile = Profiles::getProfileForCategory( category );
1004
QStringList loadList = Profiles::getPluginsForProfile( profile );
1006
QStringList ignoreList;
1008
KTrader::OfferList offers = KTrader::self()->query("KDevelop/Plugin", "[X-KDevelop-Scope] == 'Project'");
1009
KTrader::OfferList::ConstIterator itt = offers.begin();
1010
while( itt != offers.end() )
1012
if ( !loadList.contains( (*itt)->name() ) )
1014
ignoreList << (*itt)->name();
1019
DomUtil::writeListEntry( projectDOM, "/general/ignoreparts", "part", ignoreList );*/
1021
//END Plugin Profile
1023
// write the dom back
1024
if( !file.open( IO_WriteOnly ) )
1026
QTextStream ts( &file );
1027
ts << projectDOM.toString(2);
1030
// open the new project
1031
m_part->core()->openProject( projectFile );
1033
// open files to open
1034
QStringList::Iterator it = m_pCurrentAppInfo->openFilesAfterGeneration.begin();
1035
for( ; it != m_pCurrentAppInfo->openFilesAfterGeneration.end(); ++it )
1037
QString fileName( *it );
1038
if ( !fileName.isNull() )
1040
fileName = KMacroExpander::expandMacros(fileName, m_pCurrentAppInfo->subMap);
1041
m_part->partController()->editDocument( fileName );
1046
void AppWizardDialog::pageChanged()
1048
kdDebug(9010) << "AppWizardDialog::pageChanged()" << endl;
1049
projectLocationChanged();
1051
//it is possible that project name was changed - we need to update all vcs integrator dialogs
1052
for (QMap<int, VCSDialog*>::iterator it = m_integratorDialogs.begin();
1053
it != m_integratorDialogs.end(); ++it)
1054
(*it)->init(getProjectName(), getProjectLocation());
1057
void AppWizardDialog::addTemplateToFavourites()
1059
addFavourite(templates_listview->currentItem());
1062
void AppWizardDialog::addFavourite(QListViewItem* item, QString favouriteName)
1064
if(item->childCount())
1067
ApplicationInfo* info = templateForItem(item);
1069
if(!info->favourite)
1071
info->favourite = new KIconViewItem(favourites_iconview,
1072
((favouriteName=="")?info->name:favouriteName),
1073
DesktopIcon("kdevelop"));
1075
info->favourite->setRenameEnabled(true);
1079
ApplicationInfo* AppWizardDialog::findFavouriteInfo(QIconViewItem* item)
1081
QPtrListIterator<ApplicationInfo> info(m_appsInfo);
1082
for (; info.current(); ++info)
1083
if (info.current()->favourite == item)
1084
return info.current();
1089
void AppWizardDialog::favouritesIconViewClicked( QIconViewItem* item)
1091
ApplicationInfo* info = findFavouriteInfo(item);
1092
templatesTreeViewClicked(info->item);
1095
void AppWizardDialog::removeFavourite()
1097
QIconViewItem* curFavourite = favourites_iconview->currentItem();
1099
//remove reference to favourite from associated appinfo
1100
QPtrListIterator<ApplicationInfo> info(m_appsInfo);
1101
for (; info.current(); ++info)
1103
if(info.current()->favourite && info.current()->favourite == curFavourite)
1105
info.current()->favourite = 0;
1109
//remove favourite from iconview
1110
delete curFavourite;
1112
favourites_iconview->sort(); //re-arrange all items.
1115
void AppWizardDialog::populateFavourites()
1117
KConfig* config = kapp->config();
1118
config->setGroup("AppWizard");
1120
//favourites are stored in config as a list of templates and a seperate
1121
//list of icon names.
1122
QStringList templatesList = config->readPathListEntry("FavTemplates");
1123
QStringList iconNamesList = config->readListEntry("FavNames");
1125
QStringList::Iterator curTemplate = templatesList.begin();
1126
QStringList::Iterator curIconName = iconNamesList.begin();
1127
while(curTemplate != templatesList.end())
1129
QPtrListIterator<ApplicationInfo> info(m_appsInfo);
1130
for (; info.current(); ++info)
1132
if(info.current()->templateName == *curTemplate)
1134
addFavourite(info.current()->item, *curIconName);
1143
void AppWizardDialog::done(int r)
1145
//need to save the template for each favourite and
1146
//it's icon name. We have a one list for the templates
1147
//and one for the names.
1149
QStringList templatesList;
1150
QStringList iconNamesList;
1152
//Built the stringlists for each template that has a favourite.
1153
QPtrListIterator<ApplicationInfo> it(m_appsInfo);
1154
for (; it.current(); ++it)
1156
if(it.current()->favourite)
1158
templatesList.append(it.current()->templateName);
1159
iconNamesList.append(it.current()->favourite->text());
1163
KConfig* config = kapp->config();
1164
config->setGroup("AppWizard");
1165
config->writePathEntry("FavTemplates", templatesList);
1166
config->writeEntry("FavNames", iconNamesList);
1167
//config->writeEntry("CurrentTab", templates_tabwidget->currentPageIndex());
1173
void AppWizardDialog::templatesContextMenu(QListViewItem* item, const QPoint& point, int)
1175
if(item && !item->childCount())
1176
m_templatesMenu->popup(point);
1179
void AppWizardDialog::favouritesContextMenu(QIconViewItem* item, const QPoint& point)
1182
m_favouritesMenu->popup(point);
1185
void AppWizardDialog::setPermissions(const KArchiveFile *source, QString dest)
1187
kdDebug(9010) << "AppWizardDialog::setPermissions(const KArchiveFile *source, QString dest)" << endl;
1188
kdDebug(9010) << " dest: " << dest << endl;
1190
if (source->permissions() & 00100)
1192
kdDebug(9010) << "source is executable" << endl;
1193
KIO::UDSEntry entry;
1194
KURL kurl = KURL::fromPathOrURL(dest);
1195
if (KIO::NetAccess::stat(kurl, entry, 0))
1197
KFileItem it(entry, kurl);
1198
int mode = it.permissions();
1199
kdDebug(9010) << "stat shows permissions: " << mode << endl;
1200
KIO::chmod(KURL::fromPathOrURL(dest), mode | 00100 );
1205
void AppWizardDialog::setPermissions(const installFile &file)
1207
kdDebug(9010) << "AppWizardDialog::setPermissions(const installFile &file)" << endl;
1208
kdDebug(9010) << " dest: " << file.dest << endl;
1210
KIO::UDSEntry sourceentry;
1211
KURL sourceurl = KURL::fromPathOrURL(file.source);
1212
if (KIO::NetAccess::stat(sourceurl, sourceentry, 0))
1214
KFileItem sourceit(sourceentry, sourceurl);
1215
int sourcemode = sourceit.permissions();
1216
if (sourcemode & 00100)
1218
kdDebug(9010) << "source is executable" << endl;
1219
KIO::UDSEntry entry;
1220
KURL kurl = KURL::fromPathOrURL(file.dest);
1221
if (KIO::NetAccess::stat(kurl, entry, 0))
1223
KFileItem it(entry, kurl);
1224
int mode = it.permissions();
1225
kdDebug(9010) << "stat shows permissions: " << mode << endl;
1226
KIO::chmod(KURL::fromPathOrURL(file.dest), mode | 00100 );
1232
QDict<KDevLicense> AppWizardDialog::licenses()
1237
void AppWizardDialog::loadLicenses()
1239
// kdDebug(9010) << "======================== Entering loadLicenses" << endl;
1240
KStandardDirs* dirs = KGlobal::dirs();
1241
dirs->addResourceType( "licenses", KStandardDirs::kde_default( "data" ) + "kdevelop/licenses/" );
1242
QStringList licNames = dirs->findAllResources( "licenses", QString::null, false, true );
1244
QStringList::Iterator it;
1245
for (it = licNames.begin(); it != licNames.end(); ++it)
1247
QString licPath( dirs->findResource( "licenses", *it ) );
1248
kdDebug(9010) << "Loading license file: " << licPath << endl;
1249
QString licName = licPath.mid( licPath.findRev('/') + 1 );
1250
KDevLicense* lic = new KDevLicense( licName, licPath );
1251
m_licenses.insert( licName, lic );
1253
// kdDebug(9000) << "======================== Done loadLicenses" << endl;
1256
void AppWizardDialog::showTemplates(bool all)
1260
QListViewItemIterator it(templates_listview);
1261
while ( it.current() ) {
1262
it.current()->setVisible(true);
1268
QPtrListIterator<ApplicationInfo> ait(m_appsInfo);
1269
for (; ait.current(); ++ait)
1271
ait.current()->item->setVisible(m_profileSupport->isInTemplateList(ait.current()->templateName));
1274
QDictIterator<QListViewItem> dit(m_categoryMap);
1275
for (; dit.current(); ++dit)
1277
//checking whether all children are not visible
1278
kdDebug(9010) << "check: " << dit.current()->text(0) << endl;
1279
bool visible = false;
1280
QListViewItemIterator it(dit.current());
1281
while ( it.current() ) {
1282
if ((it.current()->childCount() == 0) && it.current()->isVisible())
1284
kdDebug(9010) << " visible: " << it.current()->text(0) << endl;
1290
dit.current()->setVisible(visible);
1292
checkAndHideItems(templates_listview);
1296
void AppWizardDialog::checkAndHideItems(QListView *view)
1298
QListViewItem *item = view->firstChild();
1301
if (!m_categoryItems.contains(item))
1303
checkAndHideItems(item);
1304
item = item->nextSibling();
1308
bool AppWizardDialog::checkAndHideItems(QListViewItem *item)
1310
if (!m_categoryItems.contains(item))
1311
return !item->isVisible();
1312
QListViewItem *child = item->firstChild();
1316
hide = hide && checkAndHideItems(child);
1317
child = child->nextSibling();
1319
kdDebug(9010) << "check_: " << item->text(0) << " hide: " << hide << endl;
1322
item->setVisible(false);
1328
#include "appwizarddlg.moc"
1330
// kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off;