|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2001-2002 by Bernd Gehrmann *
|
|
|
|
* bernd@tdevelop.org *
|
|
|
|
* Copyright (C) 2001 by Sandy Meier *
|
|
|
|
* smeier@tdevelop.org *
|
|
|
|
* *
|
|
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
|
|
* it under the terms of the GNU General Public License as published by *
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
|
|
* (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include "appwizarddlg.h"
|
|
|
|
|
|
|
|
#include <tqvbox.h>
|
|
|
|
#include <tqbuttongroup.h>
|
|
|
|
#include <tqcombobox.h>
|
|
|
|
#include <tqtabwidget.h>
|
|
|
|
#include <tqwidgetstack.h>
|
|
|
|
#include <tqdir.h>
|
|
|
|
#include <tqfileinfo.h>
|
|
|
|
#include <tqgrid.h>
|
|
|
|
#include <tqheader.h>
|
|
|
|
#include <tqmap.h>
|
|
|
|
#include <tqmultilineedit.h>
|
|
|
|
#include <tqpushbutton.h>
|
|
|
|
#include <tqradiobutton.h>
|
|
|
|
#include <tqregexp.h>
|
|
|
|
#include <tqtextstream.h>
|
|
|
|
#include <tqtextview.h>
|
|
|
|
#include <tqtoolbutton.h>
|
|
|
|
#include <tqtooltip.h>
|
|
|
|
#include <tqvalidator.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
#include <klistview.h>
|
|
|
|
#include <kiconview.h>
|
|
|
|
#include <kconfig.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <kglobal.h>
|
|
|
|
#include <kglobalsettings.h>
|
|
|
|
#include <klocale.h>
|
|
|
|
#include <kmessagebox.h>
|
|
|
|
#include <kprocess.h>
|
|
|
|
#include <kstandarddirs.h>
|
|
|
|
#include <ktempfile.h>
|
|
|
|
#include <kiconloader.h>
|
|
|
|
#include <kfiledialog.h>
|
|
|
|
#include <kfile.h>
|
|
|
|
#include <kapplication.h>
|
|
|
|
#include <kpopupmenu.h>
|
|
|
|
|
|
|
|
#include <ktrader.h>
|
|
|
|
#include <tdeparts/componentfactory.h>
|
|
|
|
#include <kio/netaccess.h>
|
|
|
|
#include <tqfile.h>
|
|
|
|
#include <kmacroexpander.h>
|
|
|
|
#include <karchive.h>
|
|
|
|
#include <ktar.h>
|
|
|
|
#include <ktempdir.h>
|
|
|
|
#include <kfileitem.h>
|
|
|
|
#include <kio/chmodjob.h>
|
|
|
|
|
|
|
|
#include <tqlayout.h>
|
|
|
|
|
|
|
|
#include "domutil.h"
|
|
|
|
#include "kdevversioncontrol.h"
|
|
|
|
#include "kdevmakefrontend.h"
|
|
|
|
#include "kdevpartcontroller.h"
|
|
|
|
#include "kdevplugincontroller.h"
|
|
|
|
#include "kdevappfrontend.h"
|
|
|
|
#include "kdevplugininfo.h"
|
|
|
|
#include "kdevlicense.h"
|
|
|
|
#include "kdevcore.h"
|
|
|
|
#include "appwizardfactory.h"
|
|
|
|
#include "appwizardpart.h"
|
|
|
|
#include "filepropspage.h"
|
|
|
|
#include "misc.h"
|
|
|
|
#include "profilesupport.h"
|
|
|
|
#include "filetemplate.h"
|
|
|
|
#include "settings.h"
|
|
|
|
|
|
|
|
#include "blockingkprocess.h"
|
|
|
|
|
|
|
|
#include "profileengine.h"
|
|
|
|
#include "profile.h"
|
|
|
|
|
|
|
|
#include "propeditor/property.h"
|
|
|
|
#include "propeditor/multiproperty.h"
|
|
|
|
#include "propeditor/propertylist.h"
|
|
|
|
#include "propeditor/propertyeditor.h"
|
|
|
|
|
|
|
|
AppWizardDialog::AppWizardDialog(AppWizardPart *part, TQWidget *parent, const char *name)
|
|
|
|
: AppWizardDialogBase(parent, name,true), m_pCurrentAppInfo(0),
|
|
|
|
m_profileSupport(new ProfileSupport(part))
|
|
|
|
{
|
|
|
|
kdDebug( 9010 ) << " ** AppWizardDialog::AppWizardDialog()" << endl;
|
|
|
|
|
|
|
|
m_customOptions = 0L;
|
|
|
|
loadLicenses();
|
|
|
|
connect( this, TQT_SIGNAL( selected( const TQString & ) ), this, TQT_SLOT( pageChanged() ) );
|
|
|
|
|
|
|
|
helpButton()->hide();
|
|
|
|
templates_listview->header()->hide();
|
|
|
|
templates_listview->setColumnWidthMode(0, TQListView::Maximum); //to provide horiz scrollbar.
|
|
|
|
|
|
|
|
m_templatesMenu = new KPopupMenu(templates_listview);
|
|
|
|
m_templatesMenu->insertItem(i18n("&Add to Favorites"), this, TQT_SLOT(addTemplateToFavourites()));
|
|
|
|
|
|
|
|
m_favouritesMenu = new KPopupMenu(favourites_iconview);
|
|
|
|
m_favouritesMenu->insertItem(i18n("&Remove Favorite"), this, TQT_SLOT(removeFavourite()));
|
|
|
|
|
|
|
|
m_pathIsValid=false;
|
|
|
|
m_part = part;
|
|
|
|
m_projectLocationWasChanged=false;
|
|
|
|
m_appsInfo.setAutoDelete(true);
|
|
|
|
m_tempFiles.setAutoDelete(true);
|
|
|
|
|
|
|
|
TDEConfig *config = kapp->config();
|
|
|
|
|
|
|
|
//config->setGroup("AppWizard");
|
|
|
|
//templates_tabwidget->setCurrentPage(config->readNumEntry("CurrentTab", 0));
|
|
|
|
|
|
|
|
config->setGroup("General Options");
|
|
|
|
TQString defaultProjectsDir = config->readPathEntry("DefaultProjectsDir", TQDir::homeDirPath()+"/");
|
|
|
|
|
|
|
|
KStandardDirs *dirs = AppWizardFactory::instance()->dirs();
|
|
|
|
TQStringList m_templateNames = dirs->findAllResources("apptemplates", TQString(), false, true);
|
|
|
|
|
|
|
|
kdDebug(9010) << "Templates: " << endl;
|
|
|
|
TQStringList categories;
|
|
|
|
|
|
|
|
TQStringList::Iterator it;
|
|
|
|
for (it = m_templateNames.begin(); it != m_templateNames.end(); ++it) {
|
|
|
|
kdDebug(9010) << (*it) << endl;
|
|
|
|
|
|
|
|
ApplicationInfo *info = new ApplicationInfo;
|
|
|
|
info->propValues = new PropertyLib::PropertyList();
|
|
|
|
info->templateFile = TDEGlobal::dirs()->findResource("apptemplates", *it);
|
|
|
|
info->templateName = (*it);
|
|
|
|
|
|
|
|
TDEConfig templateConfig(info->templateFile);
|
|
|
|
templateConfig.setGroup("General");
|
|
|
|
|
|
|
|
info->name = templateConfig.readEntry("Name");
|
|
|
|
info->icon = templateConfig.readEntry("Icon");
|
|
|
|
info->comment = templateConfig.readEntry("Comment");
|
|
|
|
info->fileTemplates = templateConfig.readEntry("FileTemplates");
|
|
|
|
info->openFilesAfterGeneration = templateConfig.readListEntry("ShowFilesAfterGeneration");
|
|
|
|
TQString destDir = templateConfig.readPathEntry("DefaultDestinatonDir", defaultProjectsDir);
|
|
|
|
destDir.replace(TQRegExp("HOMEDIR"), TQDir::homeDirPath());
|
|
|
|
info->defaultDestDir = destDir;
|
|
|
|
TQString category = templateConfig.readEntry("Category");
|
|
|
|
// format category to a unique status
|
|
|
|
if (category.right(1) == "/")
|
|
|
|
category.remove(category.length()-1, 1); // remove /
|
|
|
|
if (category.left(1) != "/")
|
|
|
|
category.prepend("/"); // prepend /
|
|
|
|
categories.append(category);
|
|
|
|
info->category = category;
|
|
|
|
info->sourceArchive = templateConfig.readEntry("Archive");
|
|
|
|
|
|
|
|
// Grab includes list
|
|
|
|
TQStringList groups = templateConfig.groupList();
|
|
|
|
groups.remove("General");
|
|
|
|
TQStringList::Iterator group = groups.begin();
|
|
|
|
for( ; group != groups.end(); ++group)
|
|
|
|
{
|
|
|
|
templateConfig.setGroup( (*group) );
|
|
|
|
TQString type = templateConfig.readEntry("Type").lower();
|
|
|
|
if( type == "include" ) // Add value
|
|
|
|
{
|
|
|
|
info->includes.append( templateConfig.readEntry( "File" ) );
|
|
|
|
kdDebug(9010) << "Adding: " << templateConfig.readEntry( "File" ) << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Build builtins map to bootstrap.
|
|
|
|
TQString source = kdevRoot( info->templateName );
|
|
|
|
info->subMap.insert("tdevelop", source );
|
|
|
|
|
|
|
|
// Add includes to the main template...
|
|
|
|
TQStringList::Iterator include = info->includes.begin();
|
|
|
|
for( ; include != info->includes.end(); ++include)
|
|
|
|
{
|
|
|
|
if( !(*include).isEmpty() )
|
|
|
|
{
|
|
|
|
TQString file = KMacroExpander::expandMacros( ( *include ), info->subMap);
|
|
|
|
TDEConfig tmpCfg( file );
|
|
|
|
tmpCfg.copyTo( "", &templateConfig);
|
|
|
|
kdDebug(9010) << "Merging: " << tmpCfg.name() << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
groups = templateConfig.groupList(); // Must get this again since its changed!
|
|
|
|
group = groups.begin();
|
|
|
|
for( ; group != groups.end(); ++group)
|
|
|
|
{
|
|
|
|
templateConfig.setGroup( (*group) );
|
|
|
|
TQString type = templateConfig.readEntry("Type", "value").lower();
|
|
|
|
kdDebug(9010) << "Reading " << (*group) << " of type " << type << endl;
|
|
|
|
if( type == "value" ) // Add value
|
|
|
|
{
|
|
|
|
TQString name = templateConfig.readEntry( "Value" );
|
|
|
|
TQString label = templateConfig.readEntry( "Comment" );
|
|
|
|
TQString type = templateConfig.readEntry( "ValueType", "String" );
|
|
|
|
TQVariant::Type variantType = TQVariant::nameToType( type.latin1());
|
|
|
|
TQVariant value = templateConfig.readPropertyEntry( "Default", variantType );
|
|
|
|
value.cast( variantType ); // fix this in tdelibs...
|
|
|
|
if( !name.isEmpty() && !label.isEmpty() )
|
|
|
|
info->propValues->addProperty( new PropertyLib::Property( (int)variantType, name, label, value ) );
|
|
|
|
|
|
|
|
}
|
|
|
|
else if( type == "install" ) // copy dir
|
|
|
|
{
|
|
|
|
installFile file;
|
|
|
|
file.source = templateConfig.readPathEntry("Source");
|
|
|
|
file.dest = templateConfig.readPathEntry("Dest");
|
|
|
|
file.process = templateConfig.readBoolEntry("Process",true);
|
|
|
|
file.isXML = templateConfig.readBoolEntry("EscapeXML",false);
|
|
|
|
file.option = templateConfig.readEntry("Option");
|
|
|
|
info->fileList.append(file);
|
|
|
|
}
|
|
|
|
else if( type == "install archive" )
|
|
|
|
{
|
|
|
|
installArchive arch;
|
|
|
|
arch.source = templateConfig.readPathEntry("Source");
|
|
|
|
arch.dest = templateConfig.readPathEntry("Dest");
|
|
|
|
arch.process = templateConfig.readBoolEntry("Process",true);
|
|
|
|
arch.option = templateConfig.readEntry("Option", "" );
|
|
|
|
info->archList.append(arch);
|
|
|
|
}
|
|
|
|
else if( type == "mkdir" )
|
|
|
|
{
|
|
|
|
installDir dir;
|
|
|
|
dir.dir = templateConfig.readPathEntry("Dir");
|
|
|
|
dir.option = templateConfig.readEntry("Option", "" );
|
|
|
|
dir.perms = templateConfig.readNumEntry("Perms", 0777 );
|
|
|
|
info->dirList.append(dir);
|
|
|
|
}
|
|
|
|
else if( type == "finishcmd" )
|
|
|
|
{
|
|
|
|
info->finishCmd=templateConfig.readPathEntry("Command");
|
|
|
|
info->finishCmdDir=templateConfig.readPathEntry("Directory");
|
|
|
|
}
|
|
|
|
else if( type == "ui")
|
|
|
|
{
|
|
|
|
TQString name = templateConfig.readPathEntry("File");
|
|
|
|
info->customUI = name;
|
|
|
|
}
|
|
|
|
else if( type == "message" )
|
|
|
|
{
|
|
|
|
info->message = templateConfig.readEntry( "Comment" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_appsInfo.append(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Insert categories into list view
|
|
|
|
categories.sort();
|
|
|
|
for (it = categories.begin(); it != categories.end(); ++it)
|
|
|
|
insertCategoryIntoTreeView(*it);
|
|
|
|
|
|
|
|
// Insert items into list view
|
|
|
|
TQPtrListIterator<ApplicationInfo> ait(m_appsInfo);
|
|
|
|
for (; ait.current(); ++ait) {
|
|
|
|
TQListViewItem *item = m_categoryMap.find(ait.current()->category);
|
|
|
|
if (item)
|
|
|
|
{
|
|
|
|
item = new KListViewItem(item, ait.current()->name);
|
|
|
|
item->setPixmap(0, SmallIcon("tdevelop"));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
kdDebug(9010) << "Error can't find category in categoryMap: "
|
|
|
|
<< ait.current()->category << endl;
|
|
|
|
ait.current()->item = item;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Load favourites from config
|
|
|
|
populateFavourites();
|
|
|
|
|
|
|
|
TQString author, email;
|
|
|
|
AppWizardUtil::guessAuthorAndEmail(&author, &email);
|
|
|
|
author_edit->setText(author);
|
|
|
|
email_edit->setText(email);
|
|
|
|
TQToolTip::add( dest_edit->button(), i18n("Choose projects directory") );
|
|
|
|
dest_edit->setURL(defaultProjectsDir);
|
|
|
|
dest_edit->setMode(KFile::Directory|KFile::ExistingOnly|KFile::LocalOnly);
|
|
|
|
|
|
|
|
loadVcs();
|
|
|
|
|
|
|
|
// addPage(m_sdi_fileprops_page,"Class/File Properties");
|
|
|
|
|
|
|
|
// licenseChanged();
|
|
|
|
|
|
|
|
setNextEnabled(generalPage, false);
|
|
|
|
|
|
|
|
// TQRegExp appname_regexp ("[a-zA-Z][a-zA-Z0-9_]*"); //Non-Unicode version
|
|
|
|
/* appname will start with a letter, and will contain letters,
|
|
|
|
digits or underscores. */
|
|
|
|
TQRegExp appname_regexp ("[a-zA-Z][a-zA-Z0-9_]*");
|
|
|
|
// How about names like "__" or "123" for project name? Are they legal?
|
|
|
|
TQRegExpValidator *appname_edit_validator;
|
|
|
|
appname_edit_validator = new TQRegExpValidator (appname_regexp,
|
|
|
|
TQT_TQOBJECT(appname_edit),
|
|
|
|
"AppNameValidator");
|
|
|
|
appname_edit->setValidator(appname_edit_validator);
|
|
|
|
|
|
|
|
// insert the licenses into the license_combo
|
|
|
|
TQDict< KDevLicense > lics( licenses() );
|
|
|
|
TQDictIterator< KDevLicense > dit(lics);
|
|
|
|
int idx=1;
|
|
|
|
for( ; dit.current(); ++dit )
|
|
|
|
{
|
|
|
|
license_combo->insertItem( dit.currentKey(), idx++ );
|
|
|
|
if( dit.currentKey() == "GPL" )
|
|
|
|
license_combo->setCurrentItem( idx - 1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
connect( license_combo, TQT_SIGNAL(activated(int)), this, TQT_SLOT(licenseChanged()) );
|
|
|
|
|
|
|
|
m_custom_options_layout = new TQHBoxLayout( custom_options );
|
|
|
|
m_custom_options_layout->setAutoAdd(true);
|
|
|
|
|
|
|
|
showTemplates(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
AppWizardDialog::~AppWizardDialog()
|
|
|
|
{}
|
|
|
|
|
|
|
|
void AppWizardDialog::loadVcs()
|
|
|
|
{
|
|
|
|
m_vcsForm = new VcsForm();
|
|
|
|
|
|
|
|
int i=0;
|
|
|
|
m_vcsForm->combo->insertItem( i18n("no version control system", "None"), i );
|
|
|
|
m_vcsForm->stack->addWidget( 0, i++ );
|
|
|
|
|
|
|
|
// We query for all vcs integrators for KDevelop
|
|
|
|
KTrader::OfferList offers = KTrader::self()->query("TDevelop/VCSIntegrator", "");
|
|
|
|
KTrader::OfferList::const_iterator serviceIt = offers.begin();
|
|
|
|
for (; serviceIt != offers.end(); ++serviceIt)
|
|
|
|
{
|
|
|
|
KService::Ptr service = *serviceIt;
|
|
|
|
kdDebug(9010) << "AppWizardDialog::loadVcs: creating vcs integrator "
|
|
|
|
<< service->name() << endl;
|
|
|
|
|
|
|
|
KLibFactory *factory = KLibLoader::self()->factory(TQFile::encodeName(service->library()));
|
|
|
|
if (!factory) {
|
|
|
|
TQString errorMessage = KLibLoader::self()->lastErrorMessage();
|
|
|
|
kdDebug(9010) << "There was an error loading the module " << service->name() << endl <<
|
|
|
|
"The diagnostics is:" << endl << errorMessage << endl;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TQStringList args;
|
|
|
|
TQObject *obj = factory->create(0, service->name().latin1(),
|
|
|
|
"KDevVCSIntegrator", args);
|
|
|
|
KDevVCSIntegrator *integrator = (KDevVCSIntegrator*) obj;
|
|
|
|
|
|
|
|
if (!integrator)
|
|
|
|
kdDebug(9010) << " failed to create vcs integrator " << service->name() << endl;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
kdDebug(9010) << " success" << endl;
|
|
|
|
|
|
|
|
TQString vcsName = service->property("X-TDevelop-VCS").toString();
|
|
|
|
m_vcsForm->combo->insertItem(vcsName, i);
|
|
|
|
m_integrators.insert(vcsName, integrator);
|
|
|
|
|
|
|
|
VCSDialog *vcs = integrator->integrator(m_vcsForm->stack);
|
|
|
|
if (vcs)
|
|
|
|
{
|
|
|
|
m_integratorDialogs[i] = vcs;
|
|
|
|
TQWidget *w = vcs->self();
|
|
|
|
if (w)
|
|
|
|
m_vcsForm->stack->addWidget(w, i++);
|
|
|
|
else
|
|
|
|
kdDebug(9010) << " integrator widget is 0" << endl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
kdDebug(9010) << " integrator is 0" << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addPage(m_vcsForm, i18n("Version Control System"));
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::updateNextButtons()
|
|
|
|
{
|
|
|
|
bool validGeneralPage = m_pCurrentAppInfo
|
|
|
|
&& !appname_edit->text().isEmpty()
|
|
|
|
&& m_pathIsValid;
|
|
|
|
bool validPropsPage = !version_edit->text().isEmpty()
|
|
|
|
&& !author_edit->text().isEmpty();
|
|
|
|
|
|
|
|
setFinishEnabled(m_lastPage, validGeneralPage && validPropsPage);
|
|
|
|
nextButton()->setEnabled(
|
|
|
|
currentPage() == generalPage ? validGeneralPage : validPropsPage );
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::textChanged()
|
|
|
|
{
|
|
|
|
// licenseChanged();
|
|
|
|
|
|
|
|
updateNextButtons();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::licenseChanged()
|
|
|
|
{
|
|
|
|
TQValueList<AppWizardFileTemplate>::Iterator it;
|
|
|
|
if( license_combo->currentItem() == 0 )
|
|
|
|
{
|
|
|
|
for (it = m_fileTemplates.begin(); it != m_fileTemplates.end(); ++it)
|
|
|
|
{
|
|
|
|
TQMultiLineEdit *edit = (*it).edit;
|
|
|
|
edit->setText( TQString() );
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
KDevLicense* lic = licenses()[ license_combo->currentText() ];
|
|
|
|
for (it = m_fileTemplates.begin(); it != m_fileTemplates.end(); ++it) {
|
|
|
|
TQString style = (*it).style;
|
|
|
|
TQMultiLineEdit *edit = (*it).edit;
|
|
|
|
|
|
|
|
KDevFile::CommentingStyle commentStyle = KDevFile::CPPStyle;
|
|
|
|
if (style == "PStyle") {
|
|
|
|
commentStyle = KDevFile::PascalStyle;
|
|
|
|
} else if (style == "AdaStyle") {
|
|
|
|
commentStyle = KDevFile::AdaStyle;
|
|
|
|
} else if (style == "ShellStyle") {
|
|
|
|
commentStyle = KDevFile::BashStyle;
|
|
|
|
} else if (style == "XMLStyle") {
|
|
|
|
commentStyle = KDevFile::XMLStyle;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString text;
|
|
|
|
text = lic->assemble( commentStyle, author_edit->text(), email_edit->text() , 0 );
|
|
|
|
edit->setText(text);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString AppWizardDialog::kdevRoot(const TQString &templateName ) const
|
|
|
|
{
|
|
|
|
TQString source;
|
|
|
|
TQFileInfo finfo(templateName);
|
|
|
|
TQDir dir(finfo.dir());
|
|
|
|
dir.cdUp();
|
|
|
|
return dir.absPath();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::accept()
|
|
|
|
{
|
|
|
|
TQFileInfo fi(finalLoc_label->text());
|
|
|
|
// check /again/ whether the dir already exists; maybe users create it in the meantime
|
|
|
|
if (fi.exists() ) {
|
|
|
|
KMessageBox::sorry(this, i18n("The directory you have chosen as the location for "
|
|
|
|
"the project already exists."));
|
|
|
|
showPage(generalPage);
|
|
|
|
appname_edit->setFocus();
|
|
|
|
projectLocationChanged();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !TQFileInfo(dest_edit->url()).isWritable() ){
|
|
|
|
KMessageBox::sorry(this, i18n("The directory you have chosen as the location for "
|
|
|
|
"the project is not writeable."));
|
|
|
|
showPage(generalPage);
|
|
|
|
appname_edit->setFocus();
|
|
|
|
projectLocationChanged();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString source = kdevRoot( m_pCurrentAppInfo->templateName );
|
|
|
|
|
|
|
|
// Unpack template archive to temp dir, and get the name
|
|
|
|
kdDebug(9010) << "Unpacking archive to temp dir" << endl;
|
|
|
|
KTempDir archDir;
|
|
|
|
archDir.setAutoDelete(true);
|
|
|
|
KTar templateArchive( source + "/" + m_pCurrentAppInfo->sourceArchive, "application/x-gzip" );
|
|
|
|
if( templateArchive.open( IO_ReadOnly ) )
|
|
|
|
{
|
|
|
|
//templateArchive.directory()->copyTo(archDir.name(), true);
|
|
|
|
unpackArchive(templateArchive.directory(), archDir.name(), false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
KMessageBox::sorry(this, i18n("The template %1 cannot be opened.").arg( source + "/" + m_pCurrentAppInfo->sourceArchive ) );
|
|
|
|
templateArchive.close();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
templateArchive.close();
|
|
|
|
|
|
|
|
kdDebug(9010) << "build macro map" << endl;
|
|
|
|
// Build KMacroExpander map
|
|
|
|
//m_customOptions->dataForm()->fillPropertyMap(&m_pCurrentAppInfo->subMap);
|
|
|
|
PropertyLib::PropertyList::Iterator idx = m_pCurrentAppInfo->propValues->begin();
|
|
|
|
for( ; idx != m_pCurrentAppInfo->propValues->end(); ++idx)
|
|
|
|
m_pCurrentAppInfo->subMap.insert( idx.data()->name(), idx.data()->value().toString() );
|
|
|
|
|
|
|
|
m_pCurrentAppInfo->subMap.insert("src", archDir.name() );
|
|
|
|
m_pCurrentAppInfo->subMap.insert("dest", finalLoc_label->text() );
|
|
|
|
m_pCurrentAppInfo->subMap.insert("APPNAME", appname_edit->text() );
|
|
|
|
m_pCurrentAppInfo->subMap.insert("APPNAMELC", appname_edit->text().lower() );
|
|
|
|
m_pCurrentAppInfo->subMap.insert("APPNAMESC", TQString(appname_edit->text()[0]).upper() + appname_edit->text().mid(1));
|
|
|
|
m_pCurrentAppInfo->subMap.insert("APPNAMEUC", appname_edit->text().upper() );
|
|
|
|
m_pCurrentAppInfo->subMap.insert("AUTHOR", author_edit->text() );
|
|
|
|
m_pCurrentAppInfo->subMap.insert("EMAIL", email_edit->text() );
|
|
|
|
m_pCurrentAppInfo->subMap.insert("VERSION", version_edit->text());
|
|
|
|
m_pCurrentAppInfo->subMap.insert( "I18N", "i18n" );
|
|
|
|
m_pCurrentAppInfo->subMap.insert("YEAR", TQString::number( TQDate::currentDate().year() ) );
|
|
|
|
|
|
|
|
// This isn't too pretty, but we have several templates that use TDEAboutData::License_${LICENSE}
|
|
|
|
// and unsurprisingly, TDEAboutData doesn't cover every imaginable case.
|
|
|
|
// These are the licenses known to KDE-3.2 TDEAboutData, KDevelop doesn't have all of these as prepared options today
|
|
|
|
TQString license = license_combo->currentText();
|
|
|
|
if ( license == "GPL" || license == "GPL_V2" || license == "LGPL" || license == "LGPL_V2"||
|
|
|
|
license == "BSD" || license == "NCSA" || license == "MIT" || license == "Artistic" ||
|
|
|
|
license == "QPL" || license == "TQPL_V1_0" )
|
|
|
|
{
|
|
|
|
m_pCurrentAppInfo->subMap.insert("LICENSE", license );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_pCurrentAppInfo->subMap.insert("LICENSE", "Custom" );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQStringList cleanUpSubstMap;
|
|
|
|
cleanUpSubstMap << "src" << "I18N" << "tdevelop";
|
|
|
|
|
|
|
|
|
|
|
|
kdDebug(9010) << "add template files" << endl;
|
|
|
|
// Add template files to the fileList
|
|
|
|
installDir templateDir;
|
|
|
|
templateDir.dir = "%{dest}/templates";
|
|
|
|
m_pCurrentAppInfo->dirList.prepend(templateDir);
|
|
|
|
|
|
|
|
installDir baseDir;
|
|
|
|
baseDir.dir = "%{dest}";
|
|
|
|
m_pCurrentAppInfo->dirList.prepend( baseDir );
|
|
|
|
|
|
|
|
// This is too silly for words, but it's either this or reimplementing FileTemplate
|
|
|
|
TQString tempProjectDomSource = "<!DOCTYPE tdevelop><tdevelop><general><author>%1</author><email>%2</email><version>%3</version></general></tdevelop>";
|
|
|
|
tempProjectDomSource = tempProjectDomSource.arg( author_edit->text() ).arg( email_edit->text() ).arg( version_edit->text() );
|
|
|
|
TQDomDocument tempProjectDom;
|
|
|
|
tempProjectDom.setContent( tempProjectDomSource );
|
|
|
|
|
|
|
|
TQValueList<AppWizardFileTemplate>::Iterator it;
|
|
|
|
for (it = m_fileTemplates.begin(); it != m_fileTemplates.end(); ++it) {
|
|
|
|
KTempFile *tempFile = new KTempFile();
|
|
|
|
m_tempFiles.append(tempFile);
|
|
|
|
|
|
|
|
TQString templateText( FileTemplate::makeSubstitutions( tempProjectDom, (*it).edit->text() ) );
|
|
|
|
TQFile f;
|
|
|
|
f.open(IO_WriteOnly, tempFile->handle());
|
|
|
|
TQTextStream temps(&f);
|
|
|
|
temps.setEncoding(TQTextStream::UnicodeUTF8);
|
|
|
|
temps << templateText;
|
|
|
|
f.flush();
|
|
|
|
TQString templateName( TQString( "%1_TEMPLATE" ).arg( (*it).suffix ).upper() );
|
|
|
|
cleanUpSubstMap << templateName;
|
|
|
|
m_pCurrentAppInfo->subMap.insert( templateName, KMacroExpander::expandMacros(templateText , m_pCurrentAppInfo->subMap) );
|
|
|
|
|
|
|
|
installFile file;
|
|
|
|
file.source = tempFile->name();
|
|
|
|
file.dest = TQString( "%{dest}/templates/%1" ).arg( (*it).suffix );
|
|
|
|
file.process = true;
|
|
|
|
file.isXML = false;
|
|
|
|
m_pCurrentAppInfo->fileList.append( file );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add license file to the file list
|
|
|
|
TQString licenseFile, licenseName = i18n("Custom");
|
|
|
|
|
|
|
|
if( license_combo->currentItem() != 0 )
|
|
|
|
{
|
|
|
|
licenseName = license_combo->currentText();
|
|
|
|
KDevLicense* lic = licenses()[ licenseName ];
|
|
|
|
if( lic )
|
|
|
|
{
|
|
|
|
TQStringList files( lic->copyFiles() );
|
|
|
|
TQStringList::Iterator it = files.begin();
|
|
|
|
for( ; it != files.end(); ++it )
|
|
|
|
{
|
|
|
|
installFile file;
|
|
|
|
file.source = TQString( "%{tdevelop}/template-common/%1" ).arg( *it );
|
|
|
|
file.dest = TQString("%{dest}/%1").arg( *it );
|
|
|
|
file.process = true;
|
|
|
|
file.isXML = false;
|
|
|
|
m_pCurrentAppInfo->fileList.append( file );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_pCurrentAppInfo->subMap.insert("LICENSEFILE", files.first() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run macro expander on both the dir map and file maps
|
|
|
|
TQValueList<installFile>::Iterator fileIt = m_pCurrentAppInfo->fileList.begin();
|
|
|
|
for( ; fileIt != m_pCurrentAppInfo->fileList.end(); ++fileIt)
|
|
|
|
{
|
|
|
|
(*fileIt).source = KMacroExpander::expandMacros((*fileIt).source , m_pCurrentAppInfo->subMap);
|
|
|
|
kdDebug(9010) << "Updating file dest: " << (*fileIt).dest << " with " << KMacroExpander::expandMacros((*fileIt).dest , m_pCurrentAppInfo->subMap) << endl;
|
|
|
|
(*fileIt).dest = KMacroExpander::expandMacros((*fileIt).dest , m_pCurrentAppInfo->subMap);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQValueList<installArchive>::Iterator archIt = m_pCurrentAppInfo->archList.begin();
|
|
|
|
for( ; archIt != m_pCurrentAppInfo->archList.end(); ++archIt)
|
|
|
|
{
|
|
|
|
(*archIt).source = KMacroExpander::expandMacros((*archIt).source , m_pCurrentAppInfo->subMap);
|
|
|
|
(*archIt).dest = KMacroExpander::expandMacros((*archIt).dest , m_pCurrentAppInfo->subMap);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQValueList<installDir>::Iterator dirIt = m_pCurrentAppInfo->dirList.begin();
|
|
|
|
for( ; dirIt != m_pCurrentAppInfo->dirList.end(); ++dirIt)
|
|
|
|
{
|
|
|
|
(*dirIt).dir = KMacroExpander::expandMacros((*dirIt).dir , m_pCurrentAppInfo->subMap);
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !m_pCurrentAppInfo->finishCmd.isEmpty() )
|
|
|
|
{
|
|
|
|
m_pCurrentAppInfo->finishCmd = KMacroExpander::expandMacros(
|
|
|
|
m_pCurrentAppInfo->finishCmd, m_pCurrentAppInfo->subMap );
|
|
|
|
m_pCurrentAppInfo->finishCmdDir = KMacroExpander::expandMacros(
|
|
|
|
m_pCurrentAppInfo->finishCmdDir, m_pCurrentAppInfo->subMap );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQMap<TQString,TQString>::Iterator mapIt( m_pCurrentAppInfo->subMap.begin() );
|
|
|
|
for( ; mapIt != m_pCurrentAppInfo->subMap.end(); ++mapIt )
|
|
|
|
{
|
|
|
|
TQString escaped( mapIt.data() );
|
|
|
|
escaped.replace( "&", "&" );
|
|
|
|
escaped.replace( "<", "<" );
|
|
|
|
escaped.replace( ">", ">" );
|
|
|
|
m_pCurrentAppInfo->subMapXML.insert( mapIt.key(), escaped );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create dirs
|
|
|
|
dirIt = m_pCurrentAppInfo->dirList.begin();
|
|
|
|
for( ; dirIt != m_pCurrentAppInfo->dirList.end(); ++dirIt)
|
|
|
|
{
|
|
|
|
kdDebug( 9010 ) << "Process dir " << (*dirIt).dir << endl;
|
|
|
|
if( m_pCurrentAppInfo->subMap[(*dirIt).option] != "false" )
|
|
|
|
{
|
|
|
|
if( ! TDEIO::NetAccess::mkdir( (*dirIt).dir, this ) )
|
|
|
|
{
|
|
|
|
KMessageBox::sorry(this, i18n("The directory %1 cannot be created.").arg( (*dirIt).dir ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Unpack archives
|
|
|
|
archIt = m_pCurrentAppInfo->archList.begin();
|
|
|
|
for( ; archIt != m_pCurrentAppInfo->archList.end(); ++archIt)
|
|
|
|
{
|
|
|
|
if( m_pCurrentAppInfo->subMap[(*archIt).option] != "false" )
|
|
|
|
{
|
|
|
|
kdDebug( 9010 ) << "unpacking archive " << (*archIt).source << endl;
|
|
|
|
KTar archive( (*archIt).source, "application/x-gzip" );
|
|
|
|
if( archive.open( IO_ReadOnly ) )
|
|
|
|
{
|
|
|
|
unpackArchive( archive.directory(), (*archIt).dest, (*archIt).process );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
KMessageBox::sorry(this, i18n("The archive %1 cannot be opened.").arg( (*archIt).source ) );
|
|
|
|
archive.close();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
archive.close();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Copy files & Process
|
|
|
|
fileIt = m_pCurrentAppInfo->fileList.begin();
|
|
|
|
for( ; fileIt != m_pCurrentAppInfo->fileList.end(); ++fileIt)
|
|
|
|
{
|
|
|
|
kdDebug( 9010 ) << "Process file " << (*fileIt).source << endl;
|
|
|
|
if( m_pCurrentAppInfo->subMap[(*fileIt).option] != "false" )
|
|
|
|
{
|
|
|
|
if( !copyFile( *fileIt ) )
|
|
|
|
{
|
|
|
|
KMessageBox::sorry(this, i18n("The file %1 cannot be created.").arg( (*fileIt).dest) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setPermissions(*fileIt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// if dir still does not exist
|
|
|
|
if (!fi.dir().exists()) {
|
|
|
|
KMessageBox::sorry(this, i18n("The directory above the chosen location does not exist and cannot be created."));
|
|
|
|
showPage(generalPage);
|
|
|
|
dest_edit->setFocus();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// KMessageBox::information(this, KMacroExpander::expandMacros(m_pCurrentAppInfo->message, m_pCurrentAppInfo->subMap));
|
|
|
|
|
|
|
|
TQStringList::Iterator cleanIt = cleanUpSubstMap.begin();
|
|
|
|
for(;cleanIt != cleanUpSubstMap.end(); ++cleanIt )
|
|
|
|
{
|
|
|
|
m_pCurrentAppInfo->subMap.remove( *cleanIt );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_pCurrentAppInfo->finishCmd.isEmpty())
|
|
|
|
{
|
|
|
|
BlockingTDEProcess proc;
|
|
|
|
proc.setWorkingDirectory( m_pCurrentAppInfo->finishCmdDir );
|
|
|
|
proc.setUseShell( true );
|
|
|
|
proc << "cd" << m_pCurrentAppInfo->finishCmdDir << "&&";
|
|
|
|
proc << m_pCurrentAppInfo->finishCmd;
|
|
|
|
kdDebug(9010) << "Executing:" << proc.args() << endl;
|
|
|
|
proc.start( TDEProcess::NotifyOnExit );
|
|
|
|
if( !proc.isRunning() && !proc.normalExit() )
|
|
|
|
{
|
|
|
|
kdDebug(9010) << "Couldn't execute: " << proc.args() << endl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int id = m_vcsForm->stack->id(m_vcsForm->stack->visibleWidget());
|
|
|
|
if (id)
|
|
|
|
{
|
|
|
|
VCSDialog *vcs = m_integratorDialogs[id];
|
|
|
|
if (vcs)
|
|
|
|
{
|
|
|
|
kdDebug(9010) << "vcs integrator dialog is ready" << endl;
|
|
|
|
vcs->accept();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
kdDebug(9010) << "no vcs integrator dialog" << endl;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
kdDebug(9010) << "vcs integrator wasn't selected" << endl;
|
|
|
|
|
|
|
|
openAfterGeneration();
|
|
|
|
TQWizard::accept();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AppWizardDialog::copyFile( const installFile& file )
|
|
|
|
{
|
|
|
|
kdDebug(9010) << "Copying file" << file.dest << endl;
|
|
|
|
return
|
|
|
|
copyFile( file.source, file.dest, file.isXML, file.process );
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
bool AppWizardDialog::copyFile( const TQString &source, const TQString &dest, bool isXML, bool process )
|
|
|
|
{
|
|
|
|
kdDebug( 9010 ) << "Copy: " << source << " to " << dest << endl;
|
|
|
|
if( process )
|
|
|
|
{
|
|
|
|
// Process the file and save it at the destFile location
|
|
|
|
TQFile inputFile( source);
|
|
|
|
TQFile outputFile( dest );
|
|
|
|
|
|
|
|
const TQMap<TQString,TQString> &subMap = isXML ?
|
|
|
|
m_pCurrentAppInfo->subMapXML : m_pCurrentAppInfo->subMap;
|
|
|
|
if( inputFile.open( IO_ReadOnly ) && outputFile.open(IO_WriteOnly) )
|
|
|
|
{
|
|
|
|
TQTextStream input( &inputFile );
|
|
|
|
input.setEncoding(TQTextStream::UnicodeUTF8);
|
|
|
|
TQTextStream output( &outputFile );
|
|
|
|
output.setEncoding(TQTextStream::UnicodeUTF8);
|
|
|
|
while( !input.atEnd() )
|
|
|
|
output << KMacroExpander::expandMacros(input.readLine(), subMap) << "\n";
|
|
|
|
// Preserve file mode...
|
|
|
|
struct stat fmode;
|
|
|
|
::fstat( inputFile.handle(), &fmode);
|
|
|
|
::fchmod( outputFile.handle(), fmode.st_mode );
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
inputFile.close();
|
|
|
|
outputFile.close();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Copy the source file to the destFile.
|
|
|
|
return TDEIO::NetAccess::copy( source, dest, this );
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::unpackArchive( const KArchiveDirectory *dir, const TQString &dest, bool process )
|
|
|
|
{
|
|
|
|
TDEIO::NetAccess::mkdir( dest , this );
|
|
|
|
kdDebug(9010) << "Dir : " << dir->name() << " at " << dest << endl;
|
|
|
|
TQStringList entries = dir->entries();
|
|
|
|
kdDebug(9010) << "Entries : " << entries.join(",") << endl;
|
|
|
|
|
|
|
|
KTempDir tdir;
|
|
|
|
|
|
|
|
TQStringList::Iterator entry = entries.begin();
|
|
|
|
for( ; entry != entries.end(); ++entry )
|
|
|
|
{
|
|
|
|
|
|
|
|
if( dir->entry( (*entry) )->isDirectory() )
|
|
|
|
{
|
|
|
|
const KArchiveDirectory *file = (KArchiveDirectory *)dir->entry( (*entry) );
|
|
|
|
unpackArchive( file , dest + "/" + file->name(), process);
|
|
|
|
}
|
|
|
|
else if( dir->entry( (*entry) )->isFile() )
|
|
|
|
{
|
|
|
|
const KArchiveFile *file = (KArchiveFile *) dir->entry( (*entry) );
|
|
|
|
if( !process )
|
|
|
|
{
|
|
|
|
file->copyTo( dest );
|
|
|
|
setPermissions(file, dest + "/" + file->name());
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
file->copyTo(tdir.name());
|
|
|
|
// assume that an archive does not contain XML files
|
|
|
|
// ( where should we currently get that info from? )
|
|
|
|
if ( !copyFile( TQDir::cleanDirPath(tdir.name()+"/"+file->name()), dest + "/" + file->name(), false, process ) )
|
|
|
|
{
|
|
|
|
KMessageBox::sorry(this, i18n("The file %1 cannot be created.").arg( dest) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setPermissions(file, dest + "/" + file->name());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tdir.unlink();
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::templatesTreeViewClicked(TQListViewItem *item)
|
|
|
|
{
|
|
|
|
if( m_customOptions )
|
|
|
|
delete m_customOptions;
|
|
|
|
|
|
|
|
// Delete old file template pages
|
|
|
|
while (!m_fileTemplates.isEmpty()) {
|
|
|
|
TQMultiLineEdit *edit = m_fileTemplates.first().edit;
|
|
|
|
removePage(edit);
|
|
|
|
delete edit;
|
|
|
|
m_fileTemplates.remove(m_fileTemplates.begin());
|
|
|
|
}
|
|
|
|
m_lastPage = 0;
|
|
|
|
|
|
|
|
ApplicationInfo *info = templateForItem(item);
|
|
|
|
if (info) {
|
|
|
|
m_pCurrentAppInfo = info;
|
|
|
|
if (!info->icon.isEmpty()) {
|
|
|
|
TQFileInfo fi(info->templateName);
|
|
|
|
TQDir dir(fi.dir());
|
|
|
|
dir.cdUp();
|
|
|
|
TQPixmap pm;
|
|
|
|
pm.load(dir.filePath(info->icon));
|
|
|
|
icon_label->setPixmap(pm);
|
|
|
|
} else {
|
|
|
|
icon_label->clear();
|
|
|
|
}
|
|
|
|
desc_textview->setText(info->comment);
|
|
|
|
// dest_edit->setURL(info->defaultDestDir);
|
|
|
|
m_projectLocationWasChanged = false;
|
|
|
|
//projectNameChanged(); // set the dest new
|
|
|
|
|
|
|
|
// Populate new custom options form
|
|
|
|
m_customOptions = new PropertyLib::PropertyEditor( custom_options );
|
|
|
|
m_customOptions->populateProperties(info->propValues);
|
|
|
|
|
|
|
|
|
|
|
|
// Create new file template pages
|
|
|
|
TQStringList l = TQStringList::split(",", info->fileTemplates);
|
|
|
|
if (l.empty()) //if the app template doesn't show file templates, we need to set another m_lastPage, aleXXX
|
|
|
|
m_lastPage=m_vcsForm;
|
|
|
|
|
|
|
|
TQStringList::ConstIterator it = l.begin();
|
|
|
|
while (it != l.end()) {
|
|
|
|
AppWizardFileTemplate fileTemplate;
|
|
|
|
fileTemplate.suffix = *it;
|
|
|
|
++it;
|
|
|
|
if (it != l.end()) {
|
|
|
|
fileTemplate.style = *it;
|
|
|
|
++it;
|
|
|
|
} else
|
|
|
|
fileTemplate.style = "";
|
|
|
|
|
|
|
|
TQMultiLineEdit *edit = new TQMultiLineEdit(this);
|
|
|
|
edit->setWordWrap(TQTextEdit::NoWrap);
|
|
|
|
edit->setFont(TDEGlobalSettings::fixedFont());
|
|
|
|
if (it == l.end())
|
|
|
|
m_lastPage = edit;
|
|
|
|
fileTemplate.edit = edit;
|
|
|
|
addPage(edit, i18n("Template for .%1 Files").arg(fileTemplate.suffix));
|
|
|
|
m_fileTemplates.append(fileTemplate);
|
|
|
|
}
|
|
|
|
licenseChanged(); // to populate the template views
|
|
|
|
textChanged(); // update Next button state
|
|
|
|
} else {
|
|
|
|
m_customOptions=0;
|
|
|
|
m_pCurrentAppInfo=0;
|
|
|
|
icon_label->clear();
|
|
|
|
desc_textview->clear();
|
|
|
|
nextButton()->setEnabled(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AppWizardDialog::destButtonClicked(const TQString& dir)
|
|
|
|
{
|
|
|
|
if(!dir.isEmpty()) {
|
|
|
|
|
|
|
|
// set new location as default project dir?
|
|
|
|
TDEConfig *config = kapp->config();
|
|
|
|
config->setGroup("General Options");
|
|
|
|
TQDir defPrjDir( config->readPathEntry("DefaultProjectsDir", TQDir::homeDirPath()) );
|
|
|
|
TQDir newDir (dir);
|
|
|
|
kdDebug(9010) << "DevPrjDir == newdir?: " << defPrjDir.absPath() << " == " << newDir.absPath() << endl;
|
|
|
|
if (defPrjDir != newDir) {
|
|
|
|
if (KMessageBox::questionYesNo(this, i18n("Set default project location to: %1?").arg( newDir.absPath() ),
|
|
|
|
i18n("New Project"), i18n("Set"), i18n("Do Not Set")) == KMessageBox::Yes)
|
|
|
|
{
|
|
|
|
config->writePathEntry("DefaultProjectsDir", newDir.absPath() + "/");
|
|
|
|
config->sync();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AppWizardDialog::projectNameChanged()
|
|
|
|
{
|
|
|
|
// Location was already edited by hand => don't change
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AppWizardDialog::projectLocationChanged()
|
|
|
|
{
|
|
|
|
// Jakob Simon-Gaarde: Got tired of the anoying bug with the appname/location confussion.
|
|
|
|
// This version insures WYSIWYG and checks pathvalidity
|
|
|
|
finalLoc_label->setText(dest_edit->url() + (dest_edit->url().right(1)=="/" ? "":"/") + appname_edit->text());
|
|
|
|
TQDir qd(dest_edit->url());
|
|
|
|
TQFileInfo fi(dest_edit->url() + "/" + appname_edit->text());
|
|
|
|
if (!qd.exists() || appname_edit->displayText().isEmpty()||fi.exists())
|
|
|
|
{
|
|
|
|
if (!fi.exists() || appname_edit->displayText().isEmpty()) {
|
|
|
|
finalLoc_label->setText(finalLoc_label->text() + i18n("invalid location", " (invalid)"));
|
|
|
|
} else {
|
|
|
|
finalLoc_label->setText(finalLoc_label->text() + i18n(" (dir/file already exists)"));
|
|
|
|
}
|
|
|
|
m_pathIsValid=false;
|
|
|
|
} else {
|
|
|
|
m_pathIsValid=true;
|
|
|
|
}
|
|
|
|
updateNextButtons();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AppWizardDialog::insertCategoryIntoTreeView(const TQString &completeCategoryPath)
|
|
|
|
{
|
|
|
|
kdDebug(9010) << "TemplateCategory: " << completeCategoryPath << endl;
|
|
|
|
TQStringList categories = TQStringList::split("/", completeCategoryPath);
|
|
|
|
TQString category ="";
|
|
|
|
TQListViewItem* pParentItem=0;
|
|
|
|
|
|
|
|
TQStringList::ConstIterator it;
|
|
|
|
for (it = categories.begin(); it != categories.end(); ++it) {
|
|
|
|
category = category + "/" + *it;
|
|
|
|
TQListViewItem *item = m_categoryMap.find(category);
|
|
|
|
if (!item) { // not found, create it
|
|
|
|
if (!pParentItem)
|
|
|
|
pParentItem = new KListViewItem(templates_listview,*it);
|
|
|
|
else
|
|
|
|
pParentItem = new KListViewItem(pParentItem,*it);
|
|
|
|
|
|
|
|
pParentItem->setPixmap(0, SmallIcon("folder"));
|
|
|
|
//pParentItem->setOpen(true);
|
|
|
|
kdDebug(9010) << "Category: " << category << endl;
|
|
|
|
m_categoryMap.insert(category,pParentItem);
|
|
|
|
m_categoryItems.append(pParentItem);
|
|
|
|
} else {
|
|
|
|
pParentItem = item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ApplicationInfo *AppWizardDialog::templateForItem(TQListViewItem *item)
|
|
|
|
{
|
|
|
|
TQPtrListIterator<ApplicationInfo> it(m_appsInfo);
|
|
|
|
for (; it.current(); ++it)
|
|
|
|
if (it.current()->item == item)
|
|
|
|
return it.current();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::openAfterGeneration()
|
|
|
|
{
|
|
|
|
TQString projectFile( finalLoc_label->text() + "/" + appname_edit->text().lower() + ".tdevelop" );
|
|
|
|
|
|
|
|
// Read the DOM of the newly created project
|
|
|
|
TQFile file( projectFile );
|
|
|
|
if( !file.open( IO_ReadOnly ) )
|
|
|
|
return;
|
|
|
|
TQDomDocument projectDOM;
|
|
|
|
|
|
|
|
int errorLine, errorCol;
|
|
|
|
TQString errorMsg;
|
|
|
|
bool success = projectDOM.setContent( &file, &errorMsg, &errorLine, &errorCol);
|
|
|
|
file.close();
|
|
|
|
if ( !success )
|
|
|
|
{
|
|
|
|
KMessageBox::sorry( 0, i18n("This is not a valid project file.\n"
|
|
|
|
"XML error in line %1, column %2:\n%3")
|
|
|
|
.arg(errorLine).arg(errorCol).arg(errorMsg));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// DOM Modifications go here
|
|
|
|
DomUtil::writeMapEntry( projectDOM, "substmap", m_pCurrentAppInfo->subMap );
|
|
|
|
|
|
|
|
//save the selected vcs
|
|
|
|
KTrader::OfferList offers = KTrader::self()->query("TDevelop/VCSIntegrator", TQString("[X-TDevelop-VCS]=='%1'").arg(m_vcsForm->combo->currentText()));
|
|
|
|
if (offers.count() == 1)
|
|
|
|
{
|
|
|
|
KService::Ptr service = offers.first();
|
|
|
|
DomUtil::writeEntry(projectDOM, "/general/versioncontrol", service->property("X-TDevelop-VCSPlugin").toString());
|
|
|
|
}
|
|
|
|
|
|
|
|
// figure out what plugins we should disable by default
|
|
|
|
TQString profileName = DomUtil::readEntry( projectDOM, "general/profile" );
|
|
|
|
if ( profileName.isEmpty() )
|
|
|
|
{
|
|
|
|
TQString language = DomUtil::readEntry( projectDOM, "general/primarylanguage" );
|
|
|
|
TQStringList keywords = DomUtil::readListEntry( projectDOM, "general/keywords", "keyword" );
|
|
|
|
|
|
|
|
profileName = Settings::profileByAttributes( language, keywords );
|
|
|
|
}
|
|
|
|
|
|
|
|
ProfileEngine & engine = m_part->pluginController()->engine();
|
|
|
|
Profile * profile = engine.findProfile( profileName );
|
|
|
|
|
|
|
|
TQStringList disableList;
|
|
|
|
Profile::EntryList disableEntryList = profile->list( Profile::ExplicitDisable );
|
|
|
|
for ( Profile::EntryList::const_iterator it = disableEntryList.constBegin(); it != disableEntryList.constEnd(); ++it )
|
|
|
|
{
|
|
|
|
disableList << (*it).name;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList projectIgnoreparts = DomUtil::readListEntry( projectDOM, "/general/ignoreparts", "part" );
|
|
|
|
projectIgnoreparts += disableList;
|
|
|
|
DomUtil::writeListEntry( projectDOM, "/general/ignoreparts", "part", projectIgnoreparts );
|
|
|
|
|
|
|
|
DomUtil::writeEntry( projectDOM, "/general/projectname", appname_edit->text() );
|
|
|
|
|
|
|
|
// write the dom back
|
|
|
|
if( !file.open( IO_WriteOnly ) )
|
|
|
|
return;
|
|
|
|
TQTextStream ts( &file );
|
|
|
|
ts.setEncoding(TQTextStream::UnicodeUTF8);
|
|
|
|
ts << projectDOM.toString(2);
|
|
|
|
file.close();
|
|
|
|
|
|
|
|
// open the new project
|
|
|
|
m_part->core()->openProject( projectFile );
|
|
|
|
|
|
|
|
// calculate the list of files to open after generation and use
|
|
|
|
// timer to queue opening (so that files will not be opened before the project
|
|
|
|
// which is also queued by ProjectManager )
|
|
|
|
KURL::List urlsToOpen;
|
|
|
|
TQStringList::Iterator it = m_pCurrentAppInfo->openFilesAfterGeneration.begin();
|
|
|
|
for( ; it != m_pCurrentAppInfo->openFilesAfterGeneration.end(); ++it )
|
|
|
|
{
|
|
|
|
TQString fileName( *it );
|
|
|
|
if ( !fileName.isNull() )
|
|
|
|
{
|
|
|
|
fileName = KMacroExpander::expandMacros(fileName, m_pCurrentAppInfo->subMap);
|
|
|
|
urlsToOpen.append(KURL::fromPathOrURL(fileName));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
m_part->openFilesAfterGeneration(urlsToOpen);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::pageChanged()
|
|
|
|
{
|
|
|
|
kdDebug(9010) << "AppWizardDialog::pageChanged()" << endl;
|
|
|
|
projectLocationChanged();
|
|
|
|
if (currentPage() == m_lastPage)
|
|
|
|
finishButton()->setDefault(true);
|
|
|
|
|
|
|
|
|
|
|
|
//it is possible that project name was changed - we need to update all vcs integrator dialogs
|
|
|
|
for (TQMap<int, VCSDialog*>::iterator it = m_integratorDialogs.begin();
|
|
|
|
it != m_integratorDialogs.end(); ++it)
|
|
|
|
(*it)->init(getProjectName(), getProjectLocation());
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::addTemplateToFavourites()
|
|
|
|
{
|
|
|
|
addFavourite(templates_listview->currentItem());
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::addFavourite(TQListViewItem* item, TQString favouriteName)
|
|
|
|
{
|
|
|
|
if(item->childCount())
|
|
|
|
return;
|
|
|
|
|
|
|
|
ApplicationInfo* info = templateForItem(item);
|
|
|
|
|
|
|
|
if(!info->favourite)
|
|
|
|
{
|
|
|
|
info->favourite = new KIconViewItem(favourites_iconview,
|
|
|
|
((favouriteName=="")?info->name:favouriteName),
|
|
|
|
DesktopIcon("tdevelop"));
|
|
|
|
|
|
|
|
info->favourite->setRenameEnabled(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ApplicationInfo* AppWizardDialog::findFavouriteInfo(TQIconViewItem* item)
|
|
|
|
{
|
|
|
|
TQPtrListIterator<ApplicationInfo> info(m_appsInfo);
|
|
|
|
for (; info.current(); ++info)
|
|
|
|
if (info.current()->favourite == item)
|
|
|
|
return info.current();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::favouritesIconViewClicked( TQIconViewItem* item)
|
|
|
|
{
|
|
|
|
ApplicationInfo* info = findFavouriteInfo(item);
|
|
|
|
templatesTreeViewClicked(info->item);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::removeFavourite()
|
|
|
|
{
|
|
|
|
TQIconViewItem* curFavourite = favourites_iconview->currentItem();
|
|
|
|
|
|
|
|
//remove reference to favourite from associated appinfo
|
|
|
|
TQPtrListIterator<ApplicationInfo> info(m_appsInfo);
|
|
|
|
for (; info.current(); ++info)
|
|
|
|
{
|
|
|
|
if(info.current()->favourite && info.current()->favourite == curFavourite)
|
|
|
|
{
|
|
|
|
info.current()->favourite = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//remove favourite from iconview
|
|
|
|
delete curFavourite;
|
|
|
|
curFavourite=0;
|
|
|
|
favourites_iconview->sort(); //re-arrange all items.
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::populateFavourites()
|
|
|
|
{
|
|
|
|
TDEConfig* config = kapp->config();
|
|
|
|
config->setGroup("AppWizard");
|
|
|
|
|
|
|
|
//favourites are stored in config as a list of templates and a seperate
|
|
|
|
//list of icon names.
|
|
|
|
TQStringList templatesList = config->readPathListEntry("FavTemplates");
|
|
|
|
TQStringList iconNamesList = config->readListEntry("FavNames");
|
|
|
|
|
|
|
|
TQStringList::Iterator curTemplate = templatesList.begin();
|
|
|
|
TQStringList::Iterator curIconName = iconNamesList.begin();
|
|
|
|
while(curTemplate != templatesList.end())
|
|
|
|
{
|
|
|
|
TQPtrListIterator<ApplicationInfo> info(m_appsInfo);
|
|
|
|
for (; info.current(); ++info)
|
|
|
|
{
|
|
|
|
if(info.current()->templateName == *curTemplate)
|
|
|
|
{
|
|
|
|
addFavourite(info.current()->item, *curIconName);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
curTemplate++;
|
|
|
|
curIconName++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::done(int r)
|
|
|
|
{
|
|
|
|
//need to save the template for each favourite and
|
|
|
|
//it's icon name. We have a one list for the templates
|
|
|
|
//and one for the names.
|
|
|
|
|
|
|
|
TQStringList templatesList;
|
|
|
|
TQStringList iconNamesList;
|
|
|
|
|
|
|
|
//Built the stringlists for each template that has a favourite.
|
|
|
|
TQPtrListIterator<ApplicationInfo> it(m_appsInfo);
|
|
|
|
for (; it.current(); ++it)
|
|
|
|
{
|
|
|
|
if(it.current()->favourite)
|
|
|
|
{
|
|
|
|
templatesList.append(it.current()->templateName);
|
|
|
|
iconNamesList.append(it.current()->favourite->text());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TDEConfig* config = kapp->config();
|
|
|
|
config->setGroup("AppWizard");
|
|
|
|
config->writePathEntry("FavTemplates", templatesList);
|
|
|
|
config->writeEntry("FavNames", iconNamesList);
|
|
|
|
//config->writeEntry("CurrentTab", templates_tabwidget->currentPageIndex());
|
|
|
|
config->sync();
|
|
|
|
|
|
|
|
TQDialog::done(r);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::templatesContextMenu(TQListViewItem* item, const TQPoint& point, int)
|
|
|
|
{
|
|
|
|
if(item && !item->childCount())
|
|
|
|
m_templatesMenu->popup(point);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::favouritesContextMenu(TQIconViewItem* item, const TQPoint& point)
|
|
|
|
{
|
|
|
|
if(item)
|
|
|
|
m_favouritesMenu->popup(point);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::setPermissions(const KArchiveFile *source, TQString dest)
|
|
|
|
{
|
|
|
|
kdDebug(9010) << "AppWizardDialog::setPermissions(const KArchiveFile *source, TQString dest)" << endl;
|
|
|
|
kdDebug(9010) << " dest: " << dest << endl;
|
|
|
|
|
|
|
|
if (source->permissions() & 00100)
|
|
|
|
{
|
|
|
|
kdDebug(9010) << "source is executable" << endl;
|
|
|
|
TDEIO::UDSEntry entry;
|
|
|
|
KURL kurl = KURL::fromPathOrURL(dest);
|
|
|
|
if (TDEIO::NetAccess::stat(kurl, entry, 0))
|
|
|
|
{
|
|
|
|
KFileItem it(entry, kurl);
|
|
|
|
int mode = it.permissions();
|
|
|
|
kdDebug(9010) << "stat shows permissions: " << mode << endl;
|
|
|
|
TDEIO::chmod(KURL::fromPathOrURL(dest), mode | 00100 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::setPermissions(const installFile &file)
|
|
|
|
{
|
|
|
|
kdDebug(9010) << "AppWizardDialog::setPermissions(const installFile &file)" << endl;
|
|
|
|
kdDebug(9010) << " dest: " << file.dest << endl;
|
|
|
|
|
|
|
|
TDEIO::UDSEntry sourceentry;
|
|
|
|
KURL sourceurl = KURL::fromPathOrURL(file.source);
|
|
|
|
if (TDEIO::NetAccess::stat(sourceurl, sourceentry, 0))
|
|
|
|
{
|
|
|
|
KFileItem sourceit(sourceentry, sourceurl);
|
|
|
|
int sourcemode = sourceit.permissions();
|
|
|
|
if (sourcemode & 00100)
|
|
|
|
{
|
|
|
|
kdDebug(9010) << "source is executable" << endl;
|
|
|
|
TDEIO::UDSEntry entry;
|
|
|
|
KURL kurl = KURL::fromPathOrURL(file.dest);
|
|
|
|
if (TDEIO::NetAccess::stat(kurl, entry, 0))
|
|
|
|
{
|
|
|
|
KFileItem it(entry, kurl);
|
|
|
|
int mode = it.permissions();
|
|
|
|
kdDebug(9010) << "stat shows permissions: " << mode << endl;
|
|
|
|
TDEIO::chmod(KURL::fromPathOrURL(file.dest), mode | 00100 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDict<KDevLicense> AppWizardDialog::licenses()
|
|
|
|
{
|
|
|
|
return m_licenses;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::loadLicenses()
|
|
|
|
{
|
|
|
|
// kdDebug(9010) << "======================== Entering loadLicenses" << endl;
|
|
|
|
KStandardDirs* dirs = TDEGlobal::dirs();
|
|
|
|
dirs->addResourceType( "licenses", KStandardDirs::kde_default( "data" ) + "tdevelop/licenses/" );
|
|
|
|
TQStringList licNames = dirs->findAllResources( "licenses", TQString(), false, true );
|
|
|
|
|
|
|
|
TQStringList::Iterator it;
|
|
|
|
for (it = licNames.begin(); it != licNames.end(); ++it)
|
|
|
|
{
|
|
|
|
TQString licPath( dirs->findResource( "licenses", *it ) );
|
|
|
|
kdDebug(9010) << "Loading license file: " << licPath << endl;
|
|
|
|
TQString licName = licPath.mid( licPath.findRev('/') + 1 );
|
|
|
|
KDevLicense* lic = new KDevLicense( licName, licPath );
|
|
|
|
m_licenses.insert( licName, lic );
|
|
|
|
}
|
|
|
|
// kdDebug(9010) << "======================== Done loadLicenses" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::showTemplates(bool all)
|
|
|
|
{
|
|
|
|
if (all)
|
|
|
|
{
|
|
|
|
TQListViewItemIterator it(templates_listview);
|
|
|
|
while ( it.current() ) {
|
|
|
|
it.current()->setVisible(true);
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TQPtrListIterator<ApplicationInfo> ait(m_appsInfo);
|
|
|
|
for (; ait.current(); ++ait)
|
|
|
|
{
|
|
|
|
ait.current()->item->setVisible(m_profileSupport->isInTemplateList(ait.current()->templateName));
|
|
|
|
}
|
|
|
|
|
|
|
|
TQDictIterator<TQListViewItem> dit(m_categoryMap);
|
|
|
|
for (; dit.current(); ++dit)
|
|
|
|
{
|
|
|
|
//checking whether all children are not visible
|
|
|
|
kdDebug(9010) << "check: " << dit.current()->text(0) << endl;
|
|
|
|
bool visible = false;
|
|
|
|
TQListViewItemIterator it(dit.current());
|
|
|
|
while ( it.current() ) {
|
|
|
|
if ((it.current()->childCount() == 0) && it.current()->isVisible())
|
|
|
|
{
|
|
|
|
kdDebug(9010) << " visible: " << it.current()->text(0) << endl;
|
|
|
|
visible = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
++it;
|
|
|
|
}
|
|
|
|
dit.current()->setVisible(visible);
|
|
|
|
}
|
|
|
|
checkAndHideItems(templates_listview);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppWizardDialog::checkAndHideItems(TQListView *view)
|
|
|
|
{
|
|
|
|
TQListViewItem *item = view->firstChild();
|
|
|
|
while (item)
|
|
|
|
{
|
|
|
|
if (!m_categoryItems.contains(item))
|
|
|
|
continue;
|
|
|
|
checkAndHideItems(item);
|
|
|
|
item = item->nextSibling();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool AppWizardDialog::checkAndHideItems(TQListViewItem *item)
|
|
|
|
{
|
|
|
|
if (!m_categoryItems.contains(item))
|
|
|
|
return !item->isVisible();
|
|
|
|
TQListViewItem *child = item->firstChild();
|
|
|
|
bool hide = true;
|
|
|
|
while (child)
|
|
|
|
{
|
|
|
|
hide = hide && checkAndHideItems(child);
|
|
|
|
child = child->nextSibling();
|
|
|
|
}
|
|
|
|
kdDebug(9010) << "check_: " << item->text(0) << " hide: " << hide << endl;
|
|
|
|
if (hide)
|
|
|
|
{
|
|
|
|
item->setVisible(false);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "appwizarddlg.moc"
|
|
|
|
|
|
|
|
// kate: indent-width 4; replace-tabs off; tab-width 4; space-indent off;
|