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.
piklab/src/libgui/project_manager.cpp

652 lines
23 KiB

/***************************************************************************
* Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> *
* Copyright (C) 2003 Alain Gibaud <alain.gibaud@free.fr> *
* *
* 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 "project_manager.h"
#include <tqdragobject.h>
#include <tqpainter.h>
#include <tqstyle.h>
#include <tqtimer.h>
#include <tqheader.h>
#include <klocale.h>
#include <kiconloader.h>
#include <kaction.h>
#include <kapplication.h>
#include "project.h"
#include "project_wizard.h"
#include "project_editor.h"
#include "toplevel.h"
#include "editor_manager.h"
#include "object_view.h"
#include "devices/list/device_list.h"
#include "tools/list/compile_config.h"
#include "register_view.h"
#include "hex_editor.h"
#include "main_global.h"
#include "common/gui/purl_gui.h"
#include "device_gui.h"
//----------------------------------------------------------------------------
ProjectManager::View::View(TQWidget *parent)
: ListView(parent, "project_manager"), _project(0), _modified(false)
{
connect(TQT_TQOBJECT(this), TQT_SIGNAL(mouseButtonClicked(int, TQListViewItem *, const TQPoint &, int)),
TQT_SLOT(clicked(int, TQListViewItem *, const TQPoint &, int)));
connect(TQT_TQOBJECT(this), TQT_SIGNAL(contextMenuRequested(TQListViewItem *, const TQPoint &, int)),
TQT_SLOT(contextMenu(TQListViewItem *, const TQPoint &, int)));
connect(TQT_TQOBJECT(this), TQT_SIGNAL(itemRenamed(TQListViewItem *, int, const TQString &)),
TQT_SLOT(renamed(TQListViewItem *, int, const TQString &)));
connect(TQT_TQOBJECT(this), TQT_SIGNAL(moved()), TQT_SLOT(filesReordered()));
header()->hide();
setSorting(-1);
addColumn(TQString(), 170);
setFullWidth(true);
setRootIsDecorated(false);
setAcceptDrops(true);
setDragEnabled(true);
setDropVisualizer(true);
TQTimer::singleShot(0, TQT_TQOBJECT(this), TQT_SLOT(init()));;
}
ProjectManager::View::~View()
{
delete _project;
}
void ProjectManager::View::init()
{
clear();
_rootItem = new RootItem(this);
setCurrentItem(_rootItem);
KListViewItem *item = new RegisterItem(headerItem(DeviceGroup));
ensureItemVisible(item);
_deviceItem = new DeviceItem(headerItem(DeviceGroup));
ensureItemVisible(_deviceItem);
_linkerScriptItem = 0;
(void)headerItem(SourceGroup);
}
ProjectManager::HeaderItem *ProjectManager::View::findHeaderItem(Group group) const
{
TQListViewItemIterator it(const_cast<View *>(this));
for(; it.current(); ++it) {
if ( it.current()->rtti()!=HeaderRtti ) continue;
HeaderItem *hi = static_cast<HeaderItem *>(it.current());
if ( hi->group()==group ) return hi;
}
return 0;
}
ProjectManager::HeaderItem *ProjectManager::View::headerItem(Group group)
{
HeaderItem *item = findHeaderItem(group);
if (item) return item;
item = new HeaderItem(_rootItem, group);
// reorder groups...
HeaderItem *items[Nb_Groups];
for (uint i=0; i<Nb_Groups; i++) {
items[i] = findHeaderItem(Group(i));
if (items[i]) _rootItem->takeItem(items[i]);
}
for (int i=Nb_Groups-1; i>=0; i--) {
if ( items[i]==0 ) continue;
_rootItem->insertItem(items[i]);
}
return item;
}
ProjectManager::FileItem *ProjectManager::View::findFileItem(const PURL::Url &url) const
{
TQListViewItemIterator it(const_cast<View *>(this));
for(; it.current(); ++it) {
if ( it.current()->rtti()!=FileRtti ) continue;
FileItem *fi = static_cast<FileItem *>(it.current());
if ( fi->url()==url ) return fi;
}
return 0;
}
ProjectManager::FileItem *ProjectManager::View::findFileItem(PURL::FileType type) const
{
TQListViewItemIterator it(const_cast<View *>(this));
for(; it.current(); ++it) {
if ( it.current()->rtti()!=FileRtti ) continue;
FileItem *fi = static_cast<FileItem *>(it.current());
if ( fi->ftype()==type ) return fi;
}
return 0;
}
TQListViewItem *ProjectManager::View::findItem(const TQString &tag) const
{
TQListViewItemIterator it(const_cast<View *>(this));
for(; it.current(); ++it) {
switch (Rtti(it.current()->rtti())) {
case RootRtti:
case FileRtti:
case LinkerScriptRtti:
case DeviceRtti: continue;
case HeaderRtti:
case RegisterRtti: break;
}
if ( it.current()->text(0)==tag ) return it.current();
}
return 0;
}
void ProjectManager::View::select(const Editor *e)
{
TQListViewItem *item = 0;
if ( e->url().isEmpty() ) item = findItem(e->tag());
else item = findFileItem(e->url());
if (item) setSelected(item, true);
else clearSelection();
}
void ProjectManager::View::contextMenu(TQListViewItem *item, const TQPoint &p, int)
{
if ( item==0 ) return;
PopupMenu pop;
Group group = Nb_Groups;
if ( item->rtti()==HeaderRtti) group = static_cast<const HeaderItem *>(item)->group();
if ( item->rtti()==LinkerScriptRtti || group==LinkerScriptGroup ) {
if ( _project==0 || Main::toolGroup().linkerScriptType()==PURL::Nb_FileTypes ) return;
pop.insertTitle(i18n("Linker Script"));
pop.insertItem("piklab_addfile", i18n("Set Custom..."));
if ( !_project->customLinkerScript().isEmpty() ) pop.insertItem("editdelete", i18n("Set Default"));
switch( pop.exec(p) ) {
case 1: {
PURL::Url url = PURL::getOpenUrl(":custom_linker_script", PURL::filter(Main::toolGroup().linkerScriptType()), this, i18n("Select Linker Script"));
if ( !url.isEmpty() ) _project->setCustomLinkerScript(url);
break;
}
case 2: _project->setCustomLinkerScript(PURL::Url()); break;
}
_linkerScriptItem->init();
} else if ( item->rtti()==RootRtti ) {
RootItem *ri = static_cast<RootItem *>(item);
if ( _project==0 ) {
if ( ri->url().isEmpty() ) {
pop.insertItem("piklab_createproject", i18n("New Project..."), TQT_TQOBJECT(&Main::toplevel()), TQT_SLOT(newProject()));
pop.insertItem("piklab_openproject", i18n("Open Project..."), TQT_TQOBJECT(&Main::toplevel()), TQT_SLOT(openProject()));
pop.exec(p);
} else {
pop.insertTitle(i18n("Standalone File"));
pop.insertItem("configure", i18n("Configure..."));
if ( pop.exec(p)==1 ) Main::toplevel().configure(ConfigCenter::Standalone);
}
} else {
pop.insertTitle(i18n("Project"));
pop.insertItem("configure", i18n("Options..."), TQT_TQOBJECT(&Main::toplevel()), TQT_SLOT(configureProject()));
pop.insertItem("find", i18n("Find Files..."), TQT_TQOBJECT(&Main::toplevel()), TQT_SLOT(runKfind()));
pop.insertSeparator();
pop.insertItem("piklab_compile", i18n("Build Project"), TQT_TQOBJECT(&Main::toplevel()), TQT_SLOT(buildProject()));
pop.insertItem("trashcan_empty", i18n("Clean Project"), TQT_TQOBJECT(&Main::toplevel()), TQT_SLOT(cleanBuild()));
pop.insertSeparator();
pop.insertItem("filenew", i18n("New Source File..."), TQT_TQOBJECT(&Main::toplevel()), TQT_SLOT(newSourceFile()));
pop.insertItem("piklab_addfile", i18n("Add Source Files..."), TQT_TQOBJECT(this), TQT_SLOT(insertSourceFiles()));
pop.insertItem("piklab_addfile", i18n("Add Object Files..."), TQT_TQOBJECT(this), TQT_SLOT(insertObjectFiles()));
if ( Main::currentEditor() ) pop.insertItem("piklab_addcurrentfile", i18n("Add Current File"), TQT_TQOBJECT(this), TQT_SLOT(insertCurrentFile()));
pop.exec(p);
}
} else if ( item->rtti()==FileRtti ) {
if ( _project==0 ) return;
FileItem *fi = static_cast<FileItem *>(item);
if ( isExternalFile(fi->url()) ) return;
pop.insertTitle(item->text(0));
pop.insertItem("editdelete", i18n("Remove From Project"));
if ( pop.exec(p)==1 ) removeFile(fi->url());
} else if ( item->rtti()==HeaderRtti ) {
if ( _project==0 ) return;
if ( group==LinkerObjectGroup ) {
pop.insertTitle(i18n("Objects"));
pop.insertItem("piklab_addfile", i18n("Add Object Files..."), TQT_TQOBJECT(this), TQT_SLOT(insertObjectFiles()));
pop.exec(p);
} else if ( group==SourceGroup || group==HeaderGroup ) {
pop.insertTitle(i18n("Sources"));
pop.insertItem("filenew", i18n("New File..."), TQT_TQOBJECT(&Main::toplevel()), TQT_SLOT(newSourceFile()));
pop.insertItem("piklab_addfile", i18n("Add Source Files..."), TQT_TQOBJECT(this), TQT_SLOT(insertSourceFiles()));
pop.exec(p);
} else if ( group==DeviceGroup ) {
pop.insertItem("filenew", i18n("Select Device..."), TQT_TQOBJECT(&Main::toplevel()), TQT_SLOT(showDeviceInfo()));
pop.exec(p);
}
}
}
void ProjectManager::View::closeProject()
{
if ( _project==0 && projectUrl().isEmpty() ) return;
if (_project) {
// save opened files
PURL::UrlList files = Main::editorManager().files();
PURL::UrlList::const_iterator it = files.begin();
PURL::UrlList opened;
for (; it!=files.end(); ++it) {
if ( !isExternalFile(*it) ) opened += *it;
Main::editorManager().closeEditor(*it);
}
_project->setOpenedFiles(opened);
// save watched registers
_project->setWatchedRegisters(Register::list().watched());
TQString error;
if ( !_project->save(error) )
MessageBox::detailedSorry(i18n("Could not save project file \"%1\".").tqarg(_project->url().pretty()), error, Log::Show);
delete _project;
_project = 0;
}
_modified = false;
init();
}
void ProjectManager::View::addExternalFiles()
{
const TQMap<PURL::Url, FileOrigin> &ext = projectData().externals;
TQMap<PURL::Url, FileOrigin>::const_iterator it;
for (it=ext.begin(); it!=ext.end(); ++it) {
if ( !it.key().exists() ) continue;
addFile(it.key(), it.key().fileType(), it.data());
}
}
void ProjectManager::View::setStandalone(const PURL::Url &url, PURL::FileType type)
{
if ( projectUrl()==url ) return;
closeProject();
_rootItem->set(url, true);
addFile(url, type, Intrinsic);
_standaloneData[url].type = type;
addExternalFiles();
}
PURL::Url ProjectManager::View::standaloneGenerator(const PURL::Url &url, PURL::FileType &type) const
{
TQMap<PURL::Url, ProjectData>::const_iterator it;
for (it=_standaloneData.begin(); it!=_standaloneData.end(); ++it) {
if ( !it.data().externals.contains(url) ) continue;
if ( !it.key().exists() ) continue;
type = it.data().type;
return it.key();
}
type = PURL::Nb_FileTypes;
return url;
}
void ProjectManager::View::insertSourceFiles()
{
Q_ASSERT(_project);
PURL::UrlList list = PURL::getOpenUrls(":<sources>", PURL::sourceFilter(PURL::CompleteFilter), this, i18n("Select Source File"));
if ( list.isEmpty() ) return;
PURL::UrlList::const_iterator it;
for (it=list.begin(); it!=list.end(); ++it) insertFile(*it);
}
void ProjectManager::View::insertObjectFiles()
{
Q_ASSERT(_project);
PURL::UrlList list = PURL::getOpenUrls(":<objects>", PURL::objectFilter(PURL::CompleteFilter), this, i18n("Select Object File"));
if ( list.isEmpty() ) return;
PURL::UrlList::const_iterator it;
for (it=list.begin(); it!=list.end(); ++it) insertFile(*it);
}
void ProjectManager::View::insertFile(const PURL::Url &url)
{
if ( !url.exists() ) {
MessageBox::detailedSorry(i18n("Could not find file."), i18n("File: %1").tqarg(url.pretty()), Log::Show);
return;
}
PURL::Url purl = url;
MessageBox::Result copy = MessageBox::No;
if ( !url.isInto(_project->directory()) ) {
copy = MessageBox::questionYesNoCancel(i18n("File \"%1\" is not inside the project directory. Do you want to copy the file to your project directory?").tqarg(url.pretty()),
i18n("Copy and Add"), i18n("Add only"));
if ( copy==MessageBox::Cancel ) return;
if ( copy==MessageBox::Yes ) purl = PURL::Url(_project->directory(), url.filename());
}
if ( _project->absoluteFiles().contains(purl) ) {
MessageBox::detailedSorry(i18n("File is already in the project."), i18n("File: %1").tqarg(purl.pretty()), Log::Show);
return;
}
if ( copy==MessageBox::Yes ) {
Log::StringView sview;
if ( !url.copyTo(purl, sview) ) {
MessageBox::detailedSorry(i18n("Copying file to project directory failed."), i18n("File: %1\n").tqarg(url.pretty()) + sview.string(), Log::Show);
return;
}
}
_project->addFile(purl);
addFile(purl, purl.fileType(), Intrinsic);
}
bool ProjectManager::View::openProject()
{
PURL::Url url = PURL::getOpenUrl(":open_project", PURL::projectFilter(PURL::CompleteFilter), this, i18n("Select Project file"));
return openProject(url);
}
void ProjectManager::View::addExternalFile(const PURL::Url &url, FileOrigin origin)
{
Q_ASSERT( origin!=Intrinsic );
addFile(url, url.fileType(), origin);
}
const ProjectManager::View::ProjectData &ProjectManager::View::projectData() const
{
if ( _project==0 ) return _standaloneData[projectUrl()];
return _projectData;
}
ProjectManager::View::ProjectData &ProjectManager::View::projectData()
{
if ( _project==0 ) return _standaloneData[projectUrl()];
return _projectData;
}
void ProjectManager::View::addFile(const PURL::Url &url, PURL::FileType type, FileOrigin origin)
{
if ( contains(url) ) return;
TQMap<PURL::Url, FileOrigin> &ext = projectData().externals;
if ( type.data().group==PURL::LinkerScript && _linkerScriptItem ) {
_linkerScriptItem->set(url);
ext[url] = Included;
return;
}
PURL::FileProperties properties = type.data().properties;
Group grp = Nb_Groups;
switch (origin) {
case Intrinsic: grp = group(type); break;
case Generated: grp = GeneratedGroup; break;
case Included: grp = IncludedGroup; break;
}
HeaderItem *hitem = headerItem(grp);
TQListViewItem *item = new FileItem(hitem, type, url, origin!=Intrinsic);
item->moveItem(hitem->lastChild());
ensureItemVisible(item);
if ( origin!=Intrinsic ) ext[url] = origin;
if ( type==PURL::Hex && _project==0 ) {
TQString extension = PURL::extension(PURL::AsmGPAsm);
PURL::Url durl = PURL::Url::fromPathOrUrl("<" + (url.isEmpty() ? i18n("Disassembly") : url.appendExtension(extension).filename()) + ">");
if ( findFileItem(durl)==0 ) {
(void)new FileItem(headerItem(ViewGroup), PURL::Coff, durl, true);
ext[durl] = Generated;
}
}
if ( _project && origin==Intrinsic ) _modified = true;
}
void ProjectManager::View::removeExternalFiles()
{
TQMap<PURL::Url, FileOrigin> &ext = projectData().externals;
TQMap<PURL::Url, FileOrigin>::const_iterator it;
for (it=ext.begin(); it!=ext.end(); ++it) {
Main::editorManager().closeEditor(it.key());
removeFile(it.key());
}
ext.clear();
if (_linkerScriptItem) _linkerScriptItem->init();
}
void ProjectManager::View::removeFile(const PURL::Url &url)
{
if ( _project && !isExternalFile(url) ) _project->removeFile(url);
FileItem *item = findFileItem(url);
if ( item==0 ) return;
HeaderItem *group = static_cast<HeaderItem *>(item->parent());
delete item;
if ( group->childCount()==0 ) delete group;
_modified = true;
emit guiChanged();
}
void ProjectManager::View::clicked(int button, TQListViewItem *item, const TQPoint &, int)
{
if ( item==0 ) return;
if ( button!=Qt::LeftButton ) return;
const Device::Data *data = Main::deviceData();
Rtti rtti = Rtti(item->rtti());
if ( data==0 && rtti!=DeviceRtti && rtti!=RootRtti ) {
MessageBox::sorry(i18n("Cannot open without device specified."), Log::Show);
return;
}
Editor *e = 0;
::PBusyCursor bc;
switch (rtti) {
case RootRtti:
Main::toplevel().configureProject();
break;
case HeaderRtti: {
if ( static_cast<HeaderItem *>(item)->group()!=DeviceGroup ) break;
e = Main::editorManager().openEditor(EditorManager::DeviceEditor);
break;
}
case RegisterRtti:
e = Main::editorManager().openEditor(EditorManager::RegisterEditor);
break;
case DeviceRtti: return;
case LinkerScriptRtti: {
PURL::Url url = Main::projectManager().linkerScriptUrl();
if ( url.isEmpty() ) break;
e = Main::editorManager().findEditor(url);
if ( e==0 ) {
e = Main::editorManager().createEditor(url.fileType(), url);
if ( !e->open(url) ) {
delete e;
break;
}
if ( e && isExternalFile(url) ) e->setReadOnly(true);
Main::editorManager().addEditor(e);
} else Main::editorManager().showEditor(e);
break;
}
case FileRtti: {
FileItem *fi = static_cast<FileItem *>(item);
if ( !(fi->ftype().data().properties & PURL::Editable) ) break;
e = Main::editorManager().findEditor(fi->url());
if ( e==0 ) {
if ( fi->ftype()==PURL::Coff && _project==0 && !fi->url().exists() ) {
PURL::Url url = findFileItem(PURL::Hex)->url();
if ( url.isEmpty() ) {
HexEditor *he = ::tqqt_cast<HexEditor *>(Main::currentEditor());
if ( he==0 ) break;
e = new DisassemblyEditor(*he, *data, this);
} else e = new DisassemblyEditor(url, *data, this);
addExternalFile(fi->url(), Generated);
} else e = Main::editorManager().createEditor(fi->url().fileType(), fi->url());
if ( e==0 ) break;
if ( !e->open(fi->url()) ) {
delete e;
break;
}
if ( isExternalFile(fi->url()) ) e->setReadOnly(true);
Main::editorManager().addEditor(e);
} else Main::editorManager().showEditor(e);
break;
}
}
cancelRenaming();
emit guiChanged();
}
void ProjectManager::View::insertCurrentFile()
{
insertFile(Main::editorManager().currentEditor()->url());
}
bool ProjectManager::View::editProject()
{
ProjectEditor dialog(*_project, this);
if ( dialog.exec()!=TQDialog::Accepted ) return false;
_modified = true;
if (_linkerScriptItem) _linkerScriptItem->init();
return true;
}
bool ProjectManager::View::newProject()
{
ProjectWizard wizard(this);
if ( wizard.exec()==TQDialog::Rejected ) return false;
closeProject();
TQString error;
if ( !wizard.project()->save(error) ) {
MessageBox::detailedSorry(i18n("Failed to create new project file"), error, Log::Show);
return false;
}
openProject(wizard.url());
return true;
}
void ProjectManager::View::setProject(Project *project)
{
closeProject();
Main::editorManager().closeAllEditors();
_project = project;
_rootItem->set(project->url(), false);
if ( project && Main::toolGroup().linkerScriptType()!=PURL::Nb_FileTypes ) {
_linkerScriptItem = new LinkerScriptItem(headerItem(LinkerScriptGroup));
ensureItemVisible(_linkerScriptItem);
}
}
bool ProjectManager::View::openProject(const PURL::Url &url)
{
if ( url.isEmpty() ) return false;
bool reload = ( _project && _project->url()==url );
if ( reload && !MessageBox::askContinue(i18n("Project already loaded. Reload?"), i18n("Reload")) ) return false;
static_cast< KRecentFilesAction *>(Main::action("project_open_recent"))->removeURL(url.kurl());
Project *p = new Project(url);
TQString error;
if ( !p->load(error) ) {
MessageBox::detailedSorry(i18n("Could not open project file."), error, Log::Show);
delete p;
return false;
}
setProject(p);
PURL::UrlList files = _project->absoluteFiles();
PURL::UrlList::const_iterator it;
for(it=files.begin(); it!=files.end(); ++it) addFile(*it, (*it).fileType(), Intrinsic);
_projectData.type = PURL::Project;
_projectData.externals.clear();
static_cast<KRecentFilesAction *>(Main::action("project_open_recent"))->addURL(url.kurl());
files = _project->openedFiles();
for(it = files.begin(); it!=files.end(); ++it) Main::editorManager().openFile(*it);
Register::list().init();
TQValueList<Register::TypeData> watched = _project->watchedRegisters();
TQValueList<Register::TypeData>::const_iterator wit;
for (wit=watched.begin(); wit!=watched.end(); ++wit) Register::list().setWatched(*wit, true);
return true;
}
bool ProjectManager::View::isExternalFile(const PURL::Url &url) const
{
if ( projectUrl().isEmpty() ) return false;
return projectData().externals.contains(url);
}
void ProjectManager::View::modified(const PURL::Url &url)
{
FileItem *item = findFileItem(url);
if ( item && !isExternalFile(url) ) _modified = true;
}
void ProjectManager::View::renamed(TQListViewItem *item, int, const TQString &text)
{
Q_ASSERT ( item->rtti()==DeviceRtti );
Main::toplevel().setDevice(text);
}
void ProjectManager::View::updateGUI()
{
_deviceItem->updateText();
}
TQDragObject *ProjectManager::View::dragObject()
{
if ( currentItem()==0 || currentItem()->rtti()!=FileRtti ) return 0;
const FileItem *item = static_cast<const FileItem *>(currentItem());
const HeaderItem *hitem = static_cast<const HeaderItem *>(item->parent());
if ( hitem->group()!=SourceGroup ) return 0;
TQStrList uris;
uris.append(TQUriDrag::localFileToUri(item->url().filepath()));
return new TQUriDrag(uris, viewport());
}
bool ProjectManager::View::acceptDrag(TQDropEvent* e) const
{
if ( e->source()!=viewport() ) return false;
const TQListViewItem *item = itemAt(e->pos());
if ( item==0 || item->rtti()!=FileRtti ) return false;
const HeaderItem *hitem = static_cast<const HeaderItem *>(item->parent());
return ( hitem->group()==SourceGroup );
}
void ProjectManager::View::filesReordered()
{
if ( _project==0 ) return;
_project->clearFiles();
TQListViewItem *item = headerItem(SourceGroup)->firstChild();
for (;item; item=item->nextSibling())
_project->addFile(static_cast<FileItem *>(item)->url());
}
TQString ProjectManager::View::tooltip(TQListViewItem *item, int) const
{
switch (Rtti(item->rtti())) {
case RootRtti:
case FileRtti:
case LinkerScriptRtti: return static_cast<const UrlItem *>(item)->url().filepath();
case DeviceRtti:
case RegisterRtti:
case HeaderRtti: break;
}
return TQString();
}
PURL::Url ProjectManager::View::linkerScriptUrl() const
{
TQListViewItemIterator it(const_cast<View *>(this));
for(; it.current(); ++it) {
if ( it.current()->rtti()!=LinkerScriptRtti ) continue;
return static_cast<LinkerScriptItem *>(it.current())->url();
}
return PURL::Url();
}
bool ProjectManager::View::needsRecompile() const
{
// ### this could be perfected...
PURL::Url output = projectUrl().toFileType(PURL::Hex);
TQDateTime outputLastModified;
if ( !output.exists(&outputLastModified) ) return true;
PURL::UrlList files;
if ( Main::project() ) files = Main::project()->absoluteFiles();
else files.append(projectUrl());
PURL::UrlList::const_iterator it;
for (it=files.begin(); it!=files.end(); ++it) {
TQDateTime lastModified;
if ( !(*it).exists(&lastModified) ) continue;
if ( lastModified>outputLastModified ) return true;
}
return false;
}
PURL::Url ProjectManager::View::selectedUrl() const
{
TQListViewItem *item = currentItem();
if ( item==0 ) return PURL::Url();
Rtti rtti = Rtti(item->rtti());
if ( rtti!=FileRtti ) return PURL::Url();
return static_cast<FileItem *>(item)->url();
}