You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1257 lines
29 KiB
1257 lines
29 KiB
/***************************************************************************
|
|
* Copyright (C) 2003-2005 by David Saxton *
|
|
* david@bluehaze.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 "core/ktlconfig.h"
|
|
#include "docmanager.h"
|
|
#include "document.h"
|
|
#include "language.h"
|
|
#include "languagemanager.h"
|
|
#include "ktechlab.h"
|
|
#include "microselectwidget.h"
|
|
#include "programmerdlg.h"
|
|
#include "projectdlgs.h"
|
|
#include "projectmanager.h"
|
|
#include "recentfilesaction.h"
|
|
|
|
#include <kdebug.h>
|
|
#include <kfiledialog.h>
|
|
#include <kiconloader.h>
|
|
#include <kio/netaccess.h>
|
|
#include <klocale.h>
|
|
#include <kmessagebox.h>
|
|
#include <kmimetype.h>
|
|
#include <kstandarddirs.h>
|
|
#include <qdom.h>
|
|
#include <qpopupmenu.h>
|
|
#include <qwhatsthis.h>
|
|
|
|
#include <assert.h>
|
|
|
|
//BEGIN class LinkerOptions
|
|
LinkerOptions::LinkerOptions()
|
|
{
|
|
m_hexFormat = HexFormat::inhx32;
|
|
m_bOutputMapFile = false;
|
|
}
|
|
|
|
|
|
QDomElement LinkerOptions::toDomElement( QDomDocument & doc, const KURL & baseURL ) const
|
|
{
|
|
QDomElement node = doc.createElement("linker");
|
|
|
|
node.setAttribute( "hex-format", hexFormatToString(hexFormat()) );
|
|
node.setAttribute( "output-map-file", outputMapFile() );
|
|
node.setAttribute( "library-dir", libraryDir() );
|
|
node.setAttribute( "linker-script", linkerScript() );
|
|
node.setAttribute( "other", linkerOther() );
|
|
|
|
QStringList::const_iterator end = m_linkedInternal.end();
|
|
for ( QStringList::const_iterator it = m_linkedInternal.begin(); it != end; ++it )
|
|
{
|
|
QDomElement child = doc.createElement("linked-internal");
|
|
node.appendChild(child);
|
|
child.setAttribute( "url", KURL::relativeURL( baseURL, *it ) );
|
|
}
|
|
|
|
end = m_linkedExternal.end();
|
|
for ( QStringList::const_iterator it = m_linkedExternal.begin(); it != end; ++it )
|
|
{
|
|
QDomElement child = doc.createElement("linked-external");
|
|
node.appendChild(child);
|
|
child.setAttribute( "url", *it );
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
|
|
void LinkerOptions::domElementToLinkerOptions( const QDomElement & element, const KURL & baseURL )
|
|
{
|
|
setHexFormat( stringToHexFormat( element.attribute( "hex-format", QString::null ) ) );
|
|
setOutputMapFile( element.attribute( "output-map-file", "0" ).toInt() );
|
|
setLibraryDir( element.attribute( "library-dir", QString::null ) );
|
|
setLinkerScript( element.attribute( "linker-script", QString::null ) );
|
|
setLinkerOther( element.attribute( "other", QString::null ) );
|
|
|
|
m_linkedInternal.clear();
|
|
m_linkedExternal.clear();
|
|
|
|
QDomNode node = element.firstChild();
|
|
while ( !node.isNull() )
|
|
{
|
|
QDomElement childElement = node.toElement();
|
|
if ( !childElement.isNull() )
|
|
{
|
|
const QString tagName = childElement.tagName();
|
|
|
|
if ( tagName == "linked-internal" )
|
|
m_linkedInternal << KURL( baseURL, childElement.attribute( "url", QString::null ) ).url();
|
|
|
|
else if ( tagName == "linked-external" )
|
|
m_linkedExternal << childElement.attribute( "url", QString::null );
|
|
|
|
else
|
|
kdError() << k_funcinfo << "Unrecognised element tag name: "<<tagName<<endl;
|
|
}
|
|
|
|
node = node.nextSibling();
|
|
}
|
|
}
|
|
|
|
|
|
QString LinkerOptions::hexFormatToString( HexFormat::type hexFormat )
|
|
{
|
|
switch ( hexFormat )
|
|
{
|
|
case HexFormat::inhx32:
|
|
return "inhx32";
|
|
|
|
case HexFormat::inhx8m:
|
|
return "inhx8m";
|
|
|
|
case HexFormat::inhx8s:
|
|
return "inhx8s";
|
|
|
|
case HexFormat::inhx16:
|
|
return "inhx16";
|
|
}
|
|
|
|
// Default hex format is inhx32
|
|
return "inhx32";
|
|
}
|
|
|
|
|
|
LinkerOptions::HexFormat::type LinkerOptions::stringToHexFormat( const QString & hexFormat )
|
|
{
|
|
if ( hexFormat == "inhx8m" )
|
|
return HexFormat::inhx8m;
|
|
|
|
if ( hexFormat == "inhx8s" )
|
|
return HexFormat::inhx8s;
|
|
|
|
if ( hexFormat == "inhx16" )
|
|
return HexFormat::inhx16;
|
|
|
|
return HexFormat::inhx32;
|
|
}
|
|
//END class LinkerOptions
|
|
|
|
|
|
|
|
//BEGIN class ProcessingOptions
|
|
ProcessingOptions::ProcessingOptions()
|
|
{
|
|
m_bUseParentMicroID = false;
|
|
m_microID = "P16F84";
|
|
}
|
|
|
|
|
|
ProcessingOptions::~ProcessingOptions()
|
|
{
|
|
}
|
|
|
|
|
|
QDomElement ProcessingOptions::toDomElement( QDomDocument & doc, const KURL & baseURL ) const
|
|
{
|
|
QDomElement node = doc.createElement("processing");
|
|
|
|
node.setAttribute( "output", KURL::relativeURL( baseURL, outputURL().url() ) );
|
|
node.setAttribute( "micro", m_microID );
|
|
|
|
return node;
|
|
}
|
|
|
|
|
|
void ProcessingOptions::domElementToProcessingOptions( const QDomElement & element, const KURL & baseURL )
|
|
{
|
|
setOutputURL( KURL( baseURL, element.attribute( "output", QString::null ) ) );
|
|
setMicroID( element.attribute("micro", QString::null ) );
|
|
}
|
|
//END class ProcessingOptions
|
|
|
|
|
|
|
|
//BEGIN class ProjectItem
|
|
ProjectItem::ProjectItem( ProjectItem * parent, Type type, ProjectManager * projectManager, KTechlab * ktechlab )
|
|
: QObject()
|
|
{
|
|
m_pParent = parent;
|
|
m_pILVItem = 0l;
|
|
m_pProjectManager = projectManager;
|
|
p_ktechlab = ktechlab;
|
|
m_type = type;
|
|
}
|
|
|
|
|
|
ProjectItem::~ProjectItem()
|
|
{
|
|
m_children.remove( (ProjectItem*)0l );
|
|
ProjectItemList::iterator end = m_children.end();
|
|
for ( ProjectItemList::iterator it = m_children.begin(); it != end; ++it )
|
|
(*it)->deleteLater();
|
|
m_children.clear();
|
|
|
|
delete m_pILVItem;
|
|
m_pILVItem = 0l;
|
|
}
|
|
|
|
|
|
void ProjectItem::setILVItem( ILVItem * ilvItem )
|
|
{
|
|
m_pILVItem = ilvItem;
|
|
ilvItem->setOpen(true);
|
|
ilvItem->setText( 0, name() );
|
|
ilvItem->setProjectItem(this);
|
|
updateILVItemPixmap();
|
|
}
|
|
|
|
|
|
void ProjectItem::updateILVItemPixmap()
|
|
{
|
|
if ( !m_pILVItem )
|
|
return;
|
|
|
|
switch ( type() )
|
|
{
|
|
case ProjectType:
|
|
{
|
|
// ?! - We shouldn't have an ilvitem for this.
|
|
break;
|
|
}
|
|
|
|
case ProgramType:
|
|
{
|
|
QPixmap pm;
|
|
pm.load( locate( "appdata", "icons/project_program.png" ) );
|
|
m_pILVItem->setPixmap( 0, pm );
|
|
break;
|
|
}
|
|
|
|
case LibraryType:
|
|
{
|
|
QPixmap pm;
|
|
pm.load( locate( "appdata", "icons/project_library.png" ) );
|
|
m_pILVItem->setPixmap( 0, pm );
|
|
break;
|
|
}
|
|
|
|
case FileType:
|
|
{
|
|
KMimeType::Ptr m = KMimeType::findByPath( url().path() );
|
|
m_pILVItem->setPixmap( 0, m->pixmap( KIcon::Small ) );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ProjectItem::addChild( ProjectItem * child )
|
|
{
|
|
if ( !child || m_children.contains(child) )
|
|
return;
|
|
|
|
m_children << child;
|
|
|
|
child->setILVItem( m_pILVItem ?
|
|
new ILVItem( m_pILVItem, child->name() ) :
|
|
new ILVItem( m_pProjectManager, name() ) );
|
|
|
|
updateControlChildMicroIDs();
|
|
}
|
|
|
|
|
|
void ProjectItem::updateControlChildMicroIDs()
|
|
{
|
|
bool control = false;
|
|
switch ( type() )
|
|
{
|
|
case ProjectItem::ProjectType:
|
|
case ProjectItem::LibraryType:
|
|
case ProjectItem::ProgramType:
|
|
control = !microID().isEmpty();
|
|
break;
|
|
|
|
case ProjectItem::FileType:
|
|
control = true;
|
|
break;
|
|
}
|
|
|
|
m_children.remove( (ProjectItem*)0l );
|
|
ProjectItemList::iterator end = m_children.end();
|
|
for ( ProjectItemList::iterator it = m_children.begin(); it != end; ++it )
|
|
(*it)->setUseParentMicroID( control );
|
|
}
|
|
|
|
|
|
void ProjectItem::setName( const QString & name )
|
|
{
|
|
m_name = name;
|
|
if (m_pILVItem)
|
|
m_pILVItem->setText( 0, name );
|
|
}
|
|
|
|
|
|
void ProjectItem::setURL( const KURL & url )
|
|
{
|
|
m_url = url;
|
|
|
|
if ( m_name.isEmpty() )
|
|
setName( url.fileName() );
|
|
|
|
if ( type() != FileType )
|
|
{
|
|
// The output url *is* our url
|
|
setOutputURL(url);
|
|
}
|
|
else if ( outputURL().isEmpty() )
|
|
{
|
|
// Try and guess what the output url should be...
|
|
QString newExtension;
|
|
|
|
switch ( outputType() )
|
|
{
|
|
case ProgramOutput:
|
|
newExtension = ".hex";
|
|
break;
|
|
|
|
case ObjectOutput:
|
|
newExtension = ".o";
|
|
break;
|
|
|
|
case LibraryOutput:
|
|
newExtension = ".o";
|
|
break;
|
|
|
|
case UnknownOutput:
|
|
break;
|
|
}
|
|
|
|
if ( !newExtension.isEmpty() )
|
|
{
|
|
const QString fileName = url.url();
|
|
QString extension = fileName.right( fileName.length() - fileName.findRev('.') );
|
|
setOutputURL( QString(fileName).replace( extension, newExtension ) );
|
|
}
|
|
}
|
|
|
|
updateILVItemPixmap();
|
|
}
|
|
|
|
|
|
QString ProjectItem::microID() const
|
|
{
|
|
if ( !m_bUseParentMicroID )
|
|
return m_microID;
|
|
|
|
return m_pParent ? m_pParent->microID() : QString::null;
|
|
}
|
|
|
|
|
|
void ProjectItem::setMicroID( const QString & id )
|
|
{
|
|
ProcessingOptions::setMicroID(id);
|
|
updateControlChildMicroIDs();
|
|
}
|
|
|
|
|
|
ProjectItem::OutputType ProjectItem::outputType() const
|
|
{
|
|
if ( !m_pParent )
|
|
return UnknownOutput;
|
|
|
|
switch ( m_pParent->type() )
|
|
{
|
|
case ProjectItem::ProjectType:
|
|
{
|
|
// We're a top level build target, so look at our own type
|
|
switch ( type() )
|
|
{
|
|
case ProjectItem::ProjectType:
|
|
kdWarning() << k_funcinfo << "Parent item and this item are both project items" << endl;
|
|
return UnknownOutput;
|
|
|
|
case ProjectItem::FileType:
|
|
case ProjectItem::ProgramType:
|
|
return ProgramOutput;
|
|
|
|
case ProjectItem::LibraryType:
|
|
return LibraryOutput;
|
|
}
|
|
return UnknownOutput;
|
|
}
|
|
|
|
case ProjectItem::FileType:
|
|
{
|
|
kdWarning() << k_funcinfo << "Don't know how to handle parent item being a file" << endl;
|
|
return UnknownOutput;
|
|
}
|
|
|
|
case ProjectItem::ProgramType:
|
|
case ProjectItem::LibraryType:
|
|
return ObjectOutput;
|
|
}
|
|
|
|
return UnknownOutput;
|
|
}
|
|
|
|
|
|
bool ProjectItem::build( ProcessOptionsList * pol )
|
|
{
|
|
if ( !pol )
|
|
return false;
|
|
|
|
// Check to see that we aren't already in the ProcessOptionstList;
|
|
ProcessOptionsList::iterator polEnd = pol->end();
|
|
for ( ProcessOptionsList::iterator it = pol->begin(); it != polEnd; ++it )
|
|
{
|
|
if ( (*it).targetFile() == outputURL().path() )
|
|
return true;
|
|
}
|
|
|
|
ProjectInfo * projectInfo = ProjectManager::self()->currentProject();
|
|
assert(projectInfo);
|
|
|
|
if ( outputURL().isEmpty() )
|
|
{
|
|
KMessageBox::sorry( 0l, i18n("Don't know how to build \"%1\" (output url is empty).").arg(name()) );
|
|
return false;
|
|
}
|
|
|
|
// Build all internal libraries that we depend on
|
|
QStringList::iterator send = m_linkedInternal.end();
|
|
for ( QStringList::iterator it = m_linkedInternal.begin(); it != send; ++it )
|
|
{
|
|
ProjectItem * lib = projectInfo->findItem( projectInfo->directory() + *it );
|
|
if ( !lib )
|
|
{
|
|
KMessageBox::sorry( 0l, i18n("Don't know how to build \"%1\" (library does not exist in project).").arg(*it) );
|
|
return false;
|
|
}
|
|
|
|
if ( !lib->build(pol) )
|
|
return false;
|
|
}
|
|
|
|
|
|
// Build all children
|
|
m_children.remove( (ProjectItem*)0l );
|
|
ProjectItemList::iterator cend = m_children.end();
|
|
for ( ProjectItemList::iterator it = m_children.begin(); it != cend; ++it )
|
|
{
|
|
if ( ! (*it)->build(pol) )
|
|
return false;
|
|
}
|
|
|
|
|
|
// Now build ourself
|
|
ProcessOptions po;
|
|
po.b_addToProject = false;
|
|
po.setTargetFile( outputURL().path() );
|
|
po.m_picID = microID();
|
|
|
|
ProcessOptions::ProcessPath::MediaType typeTo;
|
|
|
|
switch ( outputType() )
|
|
{
|
|
case UnknownOutput:
|
|
KMessageBox::sorry( 0l, i18n("Don't know how to build \"%1\" (unknown output type).").arg(name()) );
|
|
return false;
|
|
|
|
case ProgramOutput:
|
|
typeTo = ProcessOptions::ProcessPath::Program;
|
|
break;
|
|
|
|
case ObjectOutput:
|
|
typeTo = ProcessOptions::ProcessPath::Object;
|
|
break;
|
|
|
|
case LibraryOutput:
|
|
typeTo = ProcessOptions::ProcessPath::Library;
|
|
break;
|
|
}
|
|
|
|
switch ( type() )
|
|
{
|
|
case ProjectType:
|
|
// Nothing to do
|
|
return true;
|
|
|
|
case FileType:
|
|
po.setInputFiles( url().path() );
|
|
po.setProcessPath( ProcessOptions::ProcessPath::path( ProcessOptions::guessMediaType( url().url() ), typeTo ) );
|
|
break;
|
|
|
|
case ProgramType:
|
|
case LibraryType:
|
|
// Build up a list of input urls
|
|
QStringList inputFiles;
|
|
|
|
// Link child objects
|
|
m_children.remove( (ProjectItem*)0l );
|
|
ProjectItemList::iterator cend = m_children.end();
|
|
for ( ProjectItemList::iterator it = m_children.begin(); it != cend; ++it )
|
|
inputFiles << (*it)->outputURL().path();
|
|
|
|
po.setInputFiles(inputFiles);
|
|
po.setProcessPath( ProcessOptions::ProcessPath::path( ProcessOptions::ProcessPath::Object, typeTo ) );
|
|
break;
|
|
}
|
|
|
|
po.m_hexFormat = hexFormatToString( hexFormat() );
|
|
po.m_bOutputMapFile = outputMapFile();
|
|
po.m_libraryDir = libraryDir();
|
|
po.m_linkerScript = linkerScript();
|
|
po.m_linkOther = linkerOther();
|
|
|
|
// Link against libraries
|
|
QStringList::iterator lend = m_linkedInternal.end();
|
|
for ( QStringList::iterator it = m_linkedInternal.begin(); it != lend; ++it )
|
|
po.m_linkLibraries += projectInfo->directory() + *it;
|
|
lend = m_linkedExternal.end();
|
|
for ( QStringList::iterator it = m_linkedExternal.begin(); it != lend; ++it )
|
|
po.m_linkLibraries += *it;
|
|
|
|
// Save our working file (if open) and append to the build list
|
|
Document * currentDoc = DocManager::self()->findDocument( url() );
|
|
if (currentDoc)
|
|
currentDoc->fileSave();
|
|
pol->append(po);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void ProjectItem::upload( ProcessOptionsList * pol )
|
|
{
|
|
build( pol );
|
|
|
|
ProgrammerDlg * dlg = new ProgrammerDlg( microID(), (QWidget*)p_ktechlab, "Programmer Dlg" );
|
|
|
|
dlg->exec();
|
|
if ( !dlg->isAccepted() )
|
|
{
|
|
dlg->deleteLater();
|
|
return;
|
|
}
|
|
|
|
ProcessOptions po;
|
|
dlg->initOptions( & po );
|
|
po.b_addToProject = false;
|
|
po.setInputFiles( outputURL().path() );
|
|
po.setProcessPath( ProcessOptions::ProcessPath::Program_PIC );
|
|
|
|
pol->append( po );
|
|
|
|
dlg->deleteLater();
|
|
}
|
|
|
|
|
|
QDomElement ProjectItem::toDomElement( QDomDocument & doc, const KURL & baseURL ) const
|
|
{
|
|
QDomElement node = doc.createElement("item");
|
|
|
|
node.setAttribute( "type", typeToString() );
|
|
node.setAttribute( "name", m_name );
|
|
node.setAttribute( "url", KURL::relativeURL( baseURL, m_url.url() ) );
|
|
|
|
node.appendChild( LinkerOptions::toDomElement( doc, baseURL ) );
|
|
node.appendChild( ProcessingOptions::toDomElement( doc, baseURL ) );
|
|
|
|
|
|
ProjectItemList::const_iterator end = m_children.end();
|
|
for ( ProjectItemList::const_iterator it = m_children.begin(); it != end; ++it )
|
|
{
|
|
if (*it)
|
|
node.appendChild( (*it)->toDomElement( doc, baseURL ) );
|
|
}
|
|
|
|
return node;
|
|
}
|
|
|
|
|
|
KURL::List ProjectItem::childOutputURLs( unsigned types, unsigned outputTypes ) const
|
|
{
|
|
KURL::List urls;
|
|
|
|
ProjectItemList::const_iterator end = m_children.end();
|
|
for ( ProjectItemList::const_iterator it = m_children.begin(); it != end; ++it )
|
|
{
|
|
if (!*it)
|
|
continue;
|
|
|
|
if ( ((*it)->type() & types) && ((*it)->outputType() & outputTypes) )
|
|
urls += (*it)->outputURL().prettyURL();
|
|
|
|
urls += (*it)->childOutputURLs(types);
|
|
}
|
|
|
|
return urls;
|
|
}
|
|
|
|
|
|
ProjectItem * ProjectItem::findItem( const KURL & url )
|
|
{
|
|
if ( this->url() == url )
|
|
return this;
|
|
|
|
ProjectItemList::const_iterator end = m_children.end();
|
|
for ( ProjectItemList::const_iterator it = m_children.begin(); it != end; ++it )
|
|
{
|
|
if (!*it)
|
|
continue;
|
|
|
|
ProjectItem * found = (*it)->findItem(url);
|
|
if (found)
|
|
return found;
|
|
}
|
|
|
|
return 0l;
|
|
}
|
|
|
|
|
|
bool ProjectItem::closeOpenFiles()
|
|
{
|
|
Document * doc = DocManager::self()->findDocument(m_url);
|
|
if ( doc && !doc->fileClose() )
|
|
return false;
|
|
|
|
m_children.remove( (ProjectItem*)0l );
|
|
ProjectItemList::iterator end = m_children.end();
|
|
for ( ProjectItemList::iterator it = m_children.begin(); it != end; ++it )
|
|
{
|
|
if ( !(*it)->closeOpenFiles() )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
void ProjectItem::addFiles()
|
|
{
|
|
KURL::List urls = p_ktechlab->getFileURLs();
|
|
const KURL::List::iterator end = urls.end();
|
|
for ( KURL::List::iterator it = urls.begin(); it != end; ++ it)
|
|
addFile(*it);
|
|
}
|
|
|
|
|
|
void ProjectItem::addCurrentFile()
|
|
{
|
|
Document *document = DocManager::self()->getFocusedDocument();
|
|
if (!document)
|
|
return;
|
|
|
|
// If the file isn't saved yet, we must do that
|
|
// before it is added to the project.
|
|
if( document->url().isEmpty() )
|
|
{
|
|
document->fileSaveAs();
|
|
// If the user pressed cancel then just give up,
|
|
// otherwise the file can now be added.
|
|
}
|
|
|
|
if( !document->url().isEmpty() )
|
|
addFile( document->url() );
|
|
}
|
|
|
|
|
|
void ProjectItem::addFile( const KURL & url )
|
|
{
|
|
if ( url.isEmpty() )
|
|
return;
|
|
|
|
m_children.remove( (ProjectItem*)0l );
|
|
ProjectItemList::iterator end = m_children.end();
|
|
for ( ProjectItemList::iterator it = m_children.begin(); it != end; ++it )
|
|
{
|
|
if ( (*it)->type() == FileType && (*it)->url() == url )
|
|
return;
|
|
}
|
|
|
|
ProjectItem * item = new ProjectItem( this, FileType, m_pProjectManager, p_ktechlab );
|
|
item->setURL(url);
|
|
addChild(item);
|
|
}
|
|
|
|
|
|
QString ProjectItem::typeToString() const
|
|
{
|
|
switch (m_type)
|
|
{
|
|
case ProjectType:
|
|
return "Project";
|
|
|
|
case FileType:
|
|
return "File";
|
|
|
|
case ProgramType:
|
|
return "Program";
|
|
|
|
case LibraryType:
|
|
return "Library";
|
|
}
|
|
return QString::null;
|
|
}
|
|
|
|
|
|
ProjectItem::Type ProjectItem::stringToType( const QString & type )
|
|
{
|
|
if ( type == "Project" )
|
|
return ProjectType;
|
|
|
|
if ( type == "File" )
|
|
return FileType;
|
|
|
|
if ( type == "Program" )
|
|
return ProgramType;
|
|
|
|
if ( type == "Library" )
|
|
return LibraryType;
|
|
|
|
return FileType;
|
|
}
|
|
|
|
|
|
void ProjectItem::domElementToItem( const QDomElement & element, const KURL & baseURL )
|
|
{
|
|
Type type = stringToType( element.attribute( "type", QString::null ) );
|
|
QString name = element.attribute( "name", QString::null );
|
|
KURL url( baseURL, element.attribute( "url", QString::null ) );
|
|
|
|
ProjectItem * createdItem = new ProjectItem( this, type, m_pProjectManager, p_ktechlab );
|
|
createdItem->setName( name );
|
|
createdItem->setURL( url );
|
|
|
|
addChild( createdItem );
|
|
|
|
QDomNode node = element.firstChild();
|
|
while ( !node.isNull() )
|
|
{
|
|
QDomElement childElement = node.toElement();
|
|
if ( !childElement.isNull() )
|
|
{
|
|
const QString tagName = childElement.tagName();
|
|
|
|
if ( tagName == "linker" )
|
|
createdItem->domElementToLinkerOptions( childElement, baseURL );
|
|
|
|
else if ( tagName == "processing" )
|
|
createdItem->domElementToProcessingOptions( childElement, baseURL );
|
|
|
|
else if ( tagName == "item" )
|
|
createdItem->domElementToItem( childElement, baseURL );
|
|
|
|
else
|
|
kdError() << k_funcinfo << "Unrecognised element tag name: "<<tagName<<endl;
|
|
}
|
|
|
|
node = node.nextSibling();
|
|
}
|
|
}
|
|
//END class ProjectItem
|
|
|
|
|
|
|
|
//BEGIN class ProjectInfo
|
|
ProjectInfo::ProjectInfo( ProjectManager * projectManager, KTechlab * ktechlab )
|
|
: ProjectItem( 0l, ProjectItem::ProjectType, projectManager, ktechlab )
|
|
{
|
|
m_microID = QString::null;
|
|
}
|
|
|
|
|
|
ProjectInfo::~ ProjectInfo()
|
|
{
|
|
}
|
|
|
|
|
|
bool ProjectInfo::open( const KURL & url )
|
|
{
|
|
QString target;
|
|
if ( !KIO::NetAccess::download( url, target, 0l ) )
|
|
{
|
|
// If the file could not be downloaded, for example does not
|
|
// exist on disk, NetAccess will tell us what error to use
|
|
KMessageBox::error( 0l, KIO::NetAccess::lastErrorString() );
|
|
|
|
return false;
|
|
}
|
|
|
|
QFile file(target);
|
|
if ( !file.open( IO_ReadOnly ) )
|
|
{
|
|
KMessageBox::sorry( 0l, i18n("Could not open %1 for reading").arg(target) );
|
|
return false;
|
|
}
|
|
|
|
m_url = url;
|
|
|
|
QString xml;
|
|
QTextStream textStream( &file );
|
|
while ( !textStream.eof() )
|
|
xml += textStream.readLine() + '\n';
|
|
|
|
file.close();
|
|
|
|
QDomDocument doc( "KTechlab" );
|
|
QString errorMessage;
|
|
if ( !doc.setContent( xml, &errorMessage ) )
|
|
{
|
|
KMessageBox::sorry( 0l, i18n("Couldn't parse xml:\n%1").arg(errorMessage) );
|
|
return false;
|
|
}
|
|
|
|
QDomElement root = doc.documentElement();
|
|
|
|
QDomNode node = root.firstChild();
|
|
while ( !node.isNull() )
|
|
{
|
|
QDomElement element = node.toElement();
|
|
if ( !element.isNull() )
|
|
{
|
|
const QString tagName = element.tagName();
|
|
|
|
if ( tagName == "linker" )
|
|
domElementToLinkerOptions( element, m_url );
|
|
|
|
else if ( tagName == "processing" )
|
|
domElementToProcessingOptions( element, m_url );
|
|
|
|
else if ( tagName == "file" || tagName == "item" )
|
|
domElementToItem( element, m_url );
|
|
|
|
else
|
|
kdWarning() << k_funcinfo << "Unrecognised element tag name: "<<tagName<<endl;
|
|
}
|
|
|
|
node = node.nextSibling();
|
|
}
|
|
|
|
updateControlChildMicroIDs();
|
|
return true;
|
|
}
|
|
|
|
|
|
bool ProjectInfo::save()
|
|
{
|
|
QFile file( m_url.path() );
|
|
if ( file.open(IO_WriteOnly) == false )
|
|
{
|
|
KMessageBox::sorry( NULL, i18n("Project could not be saved to \"%1\"").arg(m_url.path()), i18n("Saving Project") );
|
|
return false;
|
|
}
|
|
|
|
QDomDocument doc("KTechlab");
|
|
|
|
QDomElement root = doc.createElement("project");
|
|
doc.appendChild(root);
|
|
|
|
// root.appendChild( LinkerOptions::toDomElement(doc) );
|
|
// root.appendChild( ProcessingOptions::toDomElement(doc) );
|
|
|
|
m_children.remove( (ProjectItem*)0l );
|
|
ProjectItemList::const_iterator end = m_children.end();
|
|
for ( ProjectItemList::const_iterator it = m_children.begin(); it != end; ++it )
|
|
root.appendChild( (*it)->toDomElement( doc, m_url ) );
|
|
|
|
QTextStream stream(&file);
|
|
stream << doc.toString();
|
|
file.close();
|
|
|
|
(static_cast<RecentFilesAction*>(p_ktechlab->action("project_open_recent")))->addURL(m_url);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool ProjectInfo::saveAndClose()
|
|
{
|
|
if (!save())
|
|
return false;
|
|
|
|
if (!closeOpenFiles())
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
//END class ProjectInfo
|
|
|
|
|
|
|
|
//BEGIN class ProjectManager
|
|
ProjectManager * ProjectManager::m_pSelf = 0l;
|
|
|
|
ProjectManager * ProjectManager::self( KTechlab * ktl, KateMDI::ToolView * parent )
|
|
{
|
|
if ( !m_pSelf )
|
|
{
|
|
assert(ktl);
|
|
assert(parent);
|
|
m_pSelf = new ProjectManager( ktl, parent );
|
|
}
|
|
return m_pSelf;
|
|
}
|
|
|
|
|
|
ProjectManager::ProjectManager( KTechlab * ktl, KateMDI::ToolView * parent )
|
|
: ItemSelector( parent, "Project Manager" ),
|
|
m_pCurrentProject(0l),
|
|
p_ktechlab(ktl)
|
|
{
|
|
QWhatsThis::add( this, i18n("Displays the list of files in the project.\nTo open or close a project, use the \"Project\" menu. Right click on a file to remove it from the project") );
|
|
|
|
setListCaption( i18n("File") );
|
|
setCaption( i18n("Project Manager") );
|
|
|
|
connect( this, SIGNAL(clicked(QListViewItem*)), this, SLOT(slotItemClicked(QListViewItem*)) );
|
|
}
|
|
|
|
|
|
ProjectManager::~ProjectManager()
|
|
{
|
|
}
|
|
|
|
|
|
void ProjectManager::slotNewProject()
|
|
{
|
|
if ( !slotCloseProject() )
|
|
return;
|
|
|
|
NewProjectDlg *newProjectDlg = new NewProjectDlg(this);
|
|
newProjectDlg->exec();
|
|
|
|
if ( newProjectDlg->accepted() )
|
|
{
|
|
m_pCurrentProject = new ProjectInfo( this, p_ktechlab );
|
|
m_pCurrentProject->setName( newProjectDlg->projectName() );
|
|
m_pCurrentProject->setURL( newProjectDlg->location() + m_pCurrentProject->name().lower() + ".ktechlab" );
|
|
|
|
QDir dir;
|
|
if ( !dir.mkdir( m_pCurrentProject->directory() ) )
|
|
kdDebug() << "Error in creating directory " << m_pCurrentProject->directory() << endl;
|
|
|
|
m_pCurrentProject->save();
|
|
updateActions();
|
|
|
|
emit projectCreated();
|
|
}
|
|
|
|
delete newProjectDlg;
|
|
}
|
|
|
|
|
|
void ProjectManager::slotProjectOptions()
|
|
{
|
|
}
|
|
|
|
|
|
void ProjectManager::slotOpenProject()
|
|
{
|
|
KURL url = KFileDialog::getOpenURL(QString::null,
|
|
"*.ktechlab|KTechlab Project(*.ktechlab)\n*|All Files", this, i18n("Open Location"));
|
|
|
|
if ( url.isEmpty() )
|
|
return;
|
|
|
|
slotOpenProject(url);
|
|
}
|
|
|
|
|
|
void ProjectManager::slotOpenProject( const KURL & url )
|
|
{
|
|
if ( m_pCurrentProject && m_pCurrentProject->url() == url )
|
|
return;
|
|
|
|
if ( !slotCloseProject() )
|
|
return;
|
|
|
|
m_pCurrentProject = new ProjectInfo( this, p_ktechlab );
|
|
|
|
if ( !m_pCurrentProject->open(url) )
|
|
{
|
|
m_pCurrentProject->deleteLater();
|
|
m_pCurrentProject = 0l;
|
|
return;
|
|
}
|
|
|
|
RecentFilesAction * rfa = static_cast<RecentFilesAction*>(p_ktechlab->action("project_open_recent"));
|
|
rfa->addURL( m_pCurrentProject->url() );
|
|
|
|
if ( KTLConfig::raiseItemSelectors() )
|
|
p_ktechlab->showToolView( p_ktechlab->toolView( toolViewIdentifier() ) );
|
|
|
|
updateActions();
|
|
emit projectOpened();
|
|
}
|
|
|
|
|
|
bool ProjectManager::slotCloseProject()
|
|
{
|
|
if ( !m_pCurrentProject )
|
|
return true;
|
|
|
|
if ( !m_pCurrentProject->saveAndClose() )
|
|
return false;
|
|
|
|
m_pCurrentProject->deleteLater();
|
|
m_pCurrentProject = 0l;
|
|
updateActions();
|
|
emit projectClosed();
|
|
return true;
|
|
}
|
|
|
|
|
|
void ProjectManager::slotCreateSubproject()
|
|
{
|
|
if ( !currentProject() )
|
|
return;
|
|
|
|
CreateSubprojectDlg * dlg = new CreateSubprojectDlg(this);
|
|
dlg->exec();
|
|
|
|
if ( dlg->accepted() )
|
|
{
|
|
ProjectItem::Type type = ProjectItem::ProgramType;
|
|
switch ( dlg->type() )
|
|
{
|
|
case CreateSubprojectDlg::ProgramType:
|
|
type = ProjectItem::ProgramType;
|
|
break;
|
|
|
|
case CreateSubprojectDlg::LibraryType:
|
|
type = ProjectItem::LibraryType;
|
|
break;
|
|
}
|
|
|
|
ProjectItem * subproject = new ProjectItem( currentProject(), type, this, p_ktechlab );
|
|
subproject->setURL( dlg->targetFile() );
|
|
|
|
currentProject()->addChild(subproject);
|
|
currentProject()->save();
|
|
|
|
emit subprojectCreated();
|
|
}
|
|
|
|
delete dlg;
|
|
}
|
|
|
|
|
|
void ProjectManager::updateActions()
|
|
{
|
|
bool projectIsOpen = m_pCurrentProject;
|
|
|
|
p_ktechlab->action("project_create_subproject")->setEnabled( projectIsOpen );
|
|
p_ktechlab->action("project_export_makefile")->setEnabled( projectIsOpen );
|
|
p_ktechlab->action("subproject_add_existing_file")->setEnabled( projectIsOpen );
|
|
p_ktechlab->action("subproject_add_current_file")->setEnabled( projectIsOpen );
|
|
// p_ktechlab->action("project_options")->setEnabled( projectIsOpen );
|
|
p_ktechlab->action("project_close")->setEnabled( projectIsOpen );
|
|
p_ktechlab->action("project_add_existing_file")->setEnabled( projectIsOpen );
|
|
p_ktechlab->action("project_add_current_file")->setEnabled( projectIsOpen );
|
|
}
|
|
|
|
|
|
void ProjectManager::slotAddFile()
|
|
{
|
|
if ( !currentProject() )
|
|
return;
|
|
|
|
currentProject()->addFiles();
|
|
emit filesAdded();
|
|
}
|
|
|
|
|
|
void ProjectManager::slotAddCurrentFile()
|
|
{
|
|
if ( !currentProject() )
|
|
return;
|
|
currentProject()->addCurrentFile();
|
|
emit filesAdded();
|
|
}
|
|
|
|
|
|
void ProjectManager::slotSubprojectAddExistingFile()
|
|
{
|
|
ILVItem * currentItem = dynamic_cast<ILVItem*>(selectedItem());
|
|
if ( !currentItem || !currentItem->projectItem() )
|
|
return;
|
|
|
|
currentItem->projectItem()->addFiles();
|
|
emit filesAdded();
|
|
}
|
|
|
|
|
|
void ProjectManager::slotSubprojectAddCurrentFile()
|
|
{
|
|
ILVItem * currentItem = dynamic_cast<ILVItem*>(selectedItem());
|
|
if ( !currentItem || !currentItem->projectItem() )
|
|
return;
|
|
|
|
currentItem->projectItem()->addCurrentFile();
|
|
emit filesAdded();
|
|
}
|
|
|
|
|
|
void ProjectManager::slotItemBuild()
|
|
{
|
|
ILVItem * currentItem = dynamic_cast<ILVItem*>(selectedItem());
|
|
if ( !currentItem || !currentItem->projectItem() )
|
|
return;
|
|
|
|
ProcessOptionsList pol;
|
|
currentItem->projectItem()->build(&pol);
|
|
LanguageManager::self()->compile(pol);
|
|
}
|
|
|
|
|
|
void ProjectManager::slotItemUpload()
|
|
{
|
|
ILVItem * currentItem = dynamic_cast<ILVItem*>(selectedItem());
|
|
if ( !currentItem || !currentItem->projectItem() )
|
|
return;
|
|
|
|
ProcessOptionsList pol;
|
|
currentItem->projectItem()->upload(&pol);
|
|
LanguageManager::self()->compile(pol);
|
|
}
|
|
|
|
|
|
void ProjectManager::slotRemoveSelected()
|
|
{
|
|
ILVItem *currentItem = dynamic_cast<ILVItem*>(selectedItem());
|
|
if ( !currentItem )
|
|
return;
|
|
|
|
int choice = KMessageBox::questionYesNo( this, i18n("Do you really want to remove \"%1\"?").arg( currentItem->text(0) ), i18n("Remove Project File?"), KGuiItem(i18n("Remove")), KGuiItem(i18n("Cancel")) );
|
|
|
|
if ( choice == KMessageBox::No )
|
|
return;
|
|
|
|
currentItem->projectItem()->deleteLater();
|
|
emit filesRemoved();
|
|
}
|
|
|
|
|
|
void ProjectManager::slotExportToMakefile()
|
|
{
|
|
}
|
|
|
|
|
|
void ProjectManager::slotSubprojectLinkerOptions()
|
|
{
|
|
ILVItem * currentItem = dynamic_cast<ILVItem*>(selectedItem());
|
|
if ( !currentItem || !currentItem->projectItem() )
|
|
return;
|
|
|
|
LinkerOptionsDlg * dlg = new LinkerOptionsDlg( currentItem->projectItem(), this );
|
|
dlg->exec();
|
|
currentProject()->save();
|
|
|
|
// The dialog sets the options for us if it was accepted, so we don't need to do anything
|
|
delete dlg;
|
|
}
|
|
|
|
|
|
void ProjectManager::slotItemProcessingOptions()
|
|
{
|
|
ILVItem * currentItem = dynamic_cast<ILVItem*>(selectedItem());
|
|
if ( !currentItem || !currentItem->projectItem() )
|
|
return;
|
|
|
|
ProcessingOptionsDlg * dlg = new ProcessingOptionsDlg( currentItem->projectItem(), this );
|
|
dlg->exec();
|
|
currentProject()->save();
|
|
|
|
// The dialog sets the options for us if it was accepted, so we don't need to do anything
|
|
delete dlg;
|
|
}
|
|
|
|
|
|
void ProjectManager::slotItemClicked( QListViewItem * item )
|
|
{
|
|
ILVItem * ilvItem = dynamic_cast<ILVItem*>(item);
|
|
if ( !ilvItem )
|
|
return;
|
|
|
|
ProjectItem * projectItem = ilvItem->projectItem();
|
|
if ( !projectItem || projectItem->type() != ProjectItem::FileType )
|
|
return;
|
|
|
|
DocManager::self()->openURL( projectItem->url() );
|
|
}
|
|
|
|
|
|
void ProjectManager::slotContextMenuRequested( QListViewItem * item, const QPoint& pos, int /*col*/ )
|
|
{
|
|
QString popupName;
|
|
ILVItem * ilvItem = dynamic_cast<ILVItem*>(item);
|
|
KAction * linkerOptionsAct = p_ktechlab->action("project_item_linker_options");
|
|
linkerOptionsAct->setEnabled(false);
|
|
|
|
if ( !m_pCurrentProject )
|
|
popupName = "project_none_popup";
|
|
|
|
else if ( !ilvItem )
|
|
popupName = "project_blank_popup";
|
|
|
|
else
|
|
{
|
|
ProcessOptions::ProcessPath::MediaType mediaType = ProcessOptions::guessMediaType( ilvItem->projectItem()->url().url() );
|
|
|
|
switch ( ilvItem->projectItem()->type() )
|
|
{
|
|
case ProjectItem::FileType:
|
|
if ( mediaType == ProcessOptions::ProcessPath::Unknown )
|
|
popupName = "project_file_other_popup";
|
|
else
|
|
popupName = "project_file_popup";
|
|
break;
|
|
|
|
case ProjectItem::ProgramType:
|
|
popupName = "project_program_popup";
|
|
break;
|
|
|
|
case ProjectItem::LibraryType:
|
|
popupName = "project_library_popup";
|
|
break;
|
|
|
|
case ProjectItem::ProjectType:
|
|
return;
|
|
}
|
|
switch ( ilvItem->projectItem()->outputType() )
|
|
{
|
|
case ProjectItem::ProgramOutput:
|
|
linkerOptionsAct->setEnabled(true);
|
|
break;
|
|
|
|
case ProjectItem::ObjectOutput:
|
|
case ProjectItem::LibraryOutput:
|
|
case ProjectItem::UnknownOutput:
|
|
linkerOptionsAct->setEnabled(false);
|
|
break;
|
|
}
|
|
|
|
// Only have linking options for SDCC files
|
|
linkerOptionsAct->setEnabled( mediaType == ProcessOptions::ProcessPath::C );
|
|
}
|
|
|
|
bool haveFocusedDocument = DocManager::self()->getFocusedDocument();
|
|
p_ktechlab->action("subproject_add_current_file")->setEnabled( haveFocusedDocument );
|
|
p_ktechlab->action("project_add_current_file")->setEnabled( haveFocusedDocument );
|
|
|
|
QPopupMenu *pop = static_cast<QPopupMenu*>(p_ktechlab->factory()->container( popupName, p_ktechlab ));
|
|
if (pop)
|
|
pop->popup(pos);
|
|
}
|
|
//END class ProjectManager
|
|
|
|
#include "projectmanager.moc"
|