// // C++ Implementation: kiledocmanager // // Description: // // // Author: Jeroen Wijnhout , (C) 2004 // Michel Ludwig , (C) 2006, 2007 // Holger Danielsson , (C) 2007 /*************************************************************************** * * * 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. * * * ***************************************************************************/ // 2007-03-12 dani // - use KileDocument::Extensions #include "kiledocmanager.h" #include #include #include #include #include #include #include "kiledebug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kileeventfilter.h" #include "kileuntitled.h" #include "templates.h" #include "newfilewizard.h" #include "managetemplatesdialog.h" #include "kileinfo.h" #include "kilejscript.h" #include "kileproject.h" #include "kiledocumentinfo.h" #include "kileviewmanager.h" #include "kilefileselect.h" #include "kileprojectview.h" #include "kilestructurewidget.h" #include "kileprojectdlgs.h" #include "kiletool.h" #include "kiletool_enums.h" #include "kilestdtools.h" #include "kilelistselector.h" #include "kiletoolmanager.h" #include "kilekonsolewidget.h" #include "kileconfig.h" #include "kilelogwidget.h" #include "cleandialog.h" /* * Newly created text documents have an empty URL and a non-empty document name. */ namespace KileDocument { Manager::Manager(KileInfo *info, TQObject *parent, const char *name) : TQObject(parent, name), m_ki(info) { m_textInfoList.setAutoDelete(false); m_projects.setAutoDelete(false); Kate::Document::setFileChangedDialogsActivated (true); if ( KileConfig::defaultEncoding() == "invalid" ) KileConfig::setDefaultEncoding(TQString::fromLatin1(TQTextCodec::codecForLocale()->name())); TQWidget *par = m_ki ? m_ki->parentWidget() : 0; m_kpd = new KProgressDialog(par, 0, i18n("Open Project..."), TQString(), true); m_kpd->showCancelButton(false); m_kpd->setLabel(i18n("Scanning project files...")); m_kpd->setAutoClose(true); m_kpd->setMinimumDuration(2000); m_kpd->cancel(); } Manager::~Manager() { KILE_DEBUG() << "==KileDocument::Manager::~Manager()=========" << endl; } void Manager::trashDoc(TextInfo *docinfo, Kate::Document *doc /*= 0L*/ ) { KILE_DEBUG() << "==void Manager::trashDoc(" << docinfo->url().path() << ")=====" << endl; if ( m_ki->isOpen(docinfo->url()) ) return; if ( doc == 0L ) doc = docinfo->getDoc(); //look for doc before we detach the docinfo //if we do it the other way around, docFor will always return nil if ( doc == 0L ) doc = docFor(docinfo->url()); KILE_DEBUG() << "DETACHING " << docinfo << endl; docinfo->detach(); KILE_DEBUG() << "\tTRASHING " << doc << endl; if ( doc == 0L ) return; KILE_DEBUG() << "just checking: docinfo->getDoc() = " << docinfo->getDoc() << endl; KILE_DEBUG() << "just checking: docFor(docinfo->url()) = " << docFor(docinfo->url()) << endl; for ( uint i = 0; i < m_textInfoList.count(); ++i ) { if ( (m_textInfoList.at(i) != docinfo) && (m_textInfoList.at(i)->getDoc() == doc) ) { KMessageBox::information(0, i18n("The internal structure of Kile is corrupted (probably due to a bug in Kile). Please select Save All from the File menu and close Kile.\nThe Kile team apologizes for any inconvenience and would appreciate a bug report.")); kdWarning() << "docinfo " << m_textInfoList.at(i) << " url " << m_textInfoList.at(i)->url().fileName() << " has a wild pointer!!!"<< endl; } } KILE_DEBUG() << "DELETING doc" << endl; delete doc; } // update all Info's with changed user commands void Manager::updateInfos() { for (uint i=0; i < m_textInfoList.count(); ++i) { m_textInfoList.at(i)->updateStructLevelInfo(); } } Kate::Document* Manager::docFor(const KURL & url) { for (uint i=0; i < m_textInfoList.count(); ++i) { if ( m_ki->similarOrEqualURL(m_textInfoList.at(i)->url(),url) ) { return m_textInfoList.at(i)->getDoc(); } } return 0L; } Info* Manager::getInfo() const { Kate::Document *doc = m_ki->activeTextDocument(); if ( doc != 0L ) return textInfoFor(doc); else return 0L; } TextInfo* Manager::textInfoFor(const TQString & path) const { if( path.isEmpty() ) return 0L; KILE_DEBUG() << "==KileInfo::textInfoFor(" << path << ")==========================" << endl; TQPtrListIterator it(m_textInfoList); while ( true ) { if ( it.current()->url().path() == path) return it.current(); if (it.atLast()) break; ++it; } KILE_DEBUG() << "\tCOULD NOT find info for " << path << endl; return 0L; } TextInfo* Manager::textInfoForURL(const KURL& url) { if( url.isEmpty() ) return 0L; KILE_DEBUG() << "==KileInfo::textInfoFor(" << url << ")==========================" << endl; TQPtrListIterator it(m_textInfoList); TextInfo *info; while ( (info = it.current()) != 0L ) { if ( info->url() == url) { return info; } ++it; } KILE_DEBUG() << "\tCOULD NOT find info for " << url << endl; return 0L; } TextInfo* Manager::textInfoFor(Kate::Document* doc) const { if( !doc ) return 0L; TQPtrListIterator it(m_textInfoList); while ( true ) { if ( it.current()->getDoc() == doc) return it.current(); if (it.atLast()) return 0L; ++it; } return 0; } void Manager::mapItem(TextInfo *docinfo, KileProjectItem *item) { item->setInfo(docinfo); } KileProject* Manager::projectFor(const KURL &projecturl) { KileProject *project = 0; //find project with url = projecturl TQPtrListIterator it(m_projects); while ( it.current() ) { if ((*it)->url() == projecturl) { return *it; } ++it; } return project; } KileProject* Manager::projectFor(const TQString &name) { KileProject *project = 0; //find project with url = projecturl TQPtrListIterator it(m_projects); while ( it.current() ) { if ((*it)->name() == name) { return *it; } ++it; } return project; } KileProjectItem* Manager::itemFor(const KURL &url, KileProject *project /*=0L*/) const { if (project == 0L) { TQPtrListIterator it(m_projects); while ( it.current() ) { KILE_DEBUG() << "looking in project " << (*it)->name() << endl; if ((*it)->contains(url)) { KILE_DEBUG() << "\t\tfound!" << endl; return (*it)->item(url); } ++it; } KILE_DEBUG() << "\t nothing found" << endl; } else { if ( project->contains(url) ) return project->item(url); } return 0L; } KileProjectItem* Manager::itemFor(Info *docinfo, KileProject *project /*=0*/) const { if(docinfo) return itemFor(docinfo->url(), project); else return 0L; } KileProjectItemList* Manager::itemsFor(Info *docinfo) const { if ( docinfo == 0 ) return 0L; KILE_DEBUG() << "==KileInfo::itemsFor(" << docinfo->url().fileName() << ")============" << endl; KileProjectItemList *list = new KileProjectItemList(); list->setAutoDelete(false); TQPtrListIterator it(m_projects); while ( it.current() ) { KILE_DEBUG() << "\tproject: " << (*it)->name() << endl; if ((*it)->contains(docinfo)) { KILE_DEBUG() << "\t\tcontains" << endl; list->append((*it)->item(docinfo)); } ++it; } return list; } bool Manager::isProjectOpen() { return ( m_projects.count() > 0 ); } KileProject* Manager::activeProject() { KileProject *curpr=0; Kate::Document *doc = m_ki->activeTextDocument(); if (doc) { for (uint i=0; i < m_projects.count(); ++i) { if (m_projects.at(i)->contains(doc->url()) ) { curpr = m_projects.at(i); break; } } } return curpr; } KileProjectItem* Manager::activeProjectItem() { KileProject *curpr = activeProject(); Kate::Document *doc = m_ki->activeTextDocument(); KileProjectItem *item = 0; if (curpr && doc) { KileProjectItemList *list = curpr->items(); for (uint i=0; i < list->count(); ++i) { if (list->at(i)->url() == doc->url()) { item = list->at(i); break; } } } return item; } TextInfo* Manager::createTextDocumentInfo(KileDocument::Type type, const KURL & url, const KURL& baseDirectory) { TextInfo *docinfo = 0L; //see if this file belongs to an opened project KileProjectItem *item = itemFor(url); if ( item != 0L ) docinfo = item->getInfo(); if ( docinfo == 0L ) { switch(type) { case Undefined: // fall through case Text: KILE_DEBUG() << "CREATING TextInfo for " << url.url() << endl; docinfo = new TextInfo(0L,m_ki->extensions()); break; case LaTeX: KILE_DEBUG() << "CREATING LaTeXInfo for " << url.url() << endl; docinfo = new LaTeXInfo(0L, m_ki->extensions(), m_ki->latexCommands(), m_ki->eventFilter()); break; case BibTeX: KILE_DEBUG() << "CREATING BibInfo for " << url.url() << endl; docinfo = new BibInfo(0L, m_ki->extensions(), m_ki->latexCommands()); break; case Script: KILE_DEBUG() << "CREATING ScriptInfo for " << url.url() << endl; docinfo = new ScriptInfo(0L, m_ki->extensions()); break; } docinfo->setBaseDirectory(baseDirectory); emit(documentInfoCreated(docinfo)); m_textInfoList.append(docinfo); } KILE_DEBUG() << "DOCINFO: returning " << docinfo << " " << docinfo->url().fileName() << endl; return docinfo; } void Manager::recreateTextDocumentInfo(TextInfo *oldinfo) { KileProjectItemList *list = itemsFor(oldinfo); KURL url = oldinfo->url(); TextInfo *newinfo = createTextDocumentInfo(m_ki->extensions()->determineDocumentType(url), url, oldinfo->getBaseDirectory()); newinfo->setDoc(oldinfo->getDoc()); KileProjectItem *pritem = 0L; for ( pritem = list->first(); pritem; pritem = list->next() ) { pritem->setInfo(newinfo); } removeTextDocumentInfo(oldinfo); emit(updateStructure(true, newinfo)); } bool Manager::removeTextDocumentInfo(TextInfo *docinfo, bool closingproject /* = false */) { KILE_DEBUG() << "==Manager::removeTextDocumentInfo(Info *docinfo)=====" << endl; KileProjectItemList *itms = itemsFor(docinfo); bool oneItem = false; if (itms->count() == 1) oneItem = true; if (itms->count() == 0 || ( closingproject && oneItem )) { KILE_DEBUG() << "\tremoving " << docinfo << " count = " << m_textInfoList.count() << endl; m_textInfoList.remove(docinfo); emit ( closingDocument ( docinfo ) ); cleanupDocumentInfoForProjectItems(docinfo); delete docinfo; delete itms; return true; } KILE_DEBUG() << "\tnot removing " << docinfo << endl; delete itms; return false; } Kate::Document* Manager::createDocument(const TQString& name, const KURL& url, TextInfo *docinfo, const TQString & encoding, const TQString & highlight) { KILE_DEBUG() << "==Kate::Document* Manager::createDocument()===========" << endl; Kate::Document *doc = (Kate::Document*) KTextEditor::createDocument ("libkatepart", this, "Kate::Document"); if ( docFor(url) != 0L ) kdWarning() << url << " already has a document!" << endl; else KILE_DEBUG() << "\tappending document " << doc << endl; //set the default encoding TQString enc = encoding.isNull() ? KileConfig::defaultEncoding() : encoding; doc->setEncoding(enc); KILE_DEBUG() << "url is = " << docinfo->url() << endl; if(!url.isEmpty()) { bool r = doc->openURL(url); // don't add scripts to the recent files if(r && docinfo->getType() != Script) { emit(addToRecentFiles(url)); } } doc->setDocName(name.isEmpty() ? url.fileName() : name); //handle changes of the document connect(doc, TQT_SIGNAL(nameChanged(Kate::Document *)), m_ki->parentWidget(), TQT_SLOT(newCaption())); connect(doc, TQT_SIGNAL(fileNameChanged()), m_ki->parentWidget(), TQT_SLOT(newCaption())); connect(doc, TQT_SIGNAL(modStateChanged(Kate::Document*)), this, TQT_SLOT(newDocumentStatus(Kate::Document*))); connect(doc, TQT_SIGNAL(modifiedOnDisc(Kate::Document*, bool, unsigned char)), this, TQT_SIGNAL(documentStatusChanged(Kate::Document*, bool, unsigned char))); docinfo->setDoc(doc); docinfo->setHighlightMode(highlight); // FIXME: the whole structure updating stuff needs to be rewritten; updates should originate from // the docinfo only, i.e. the structure view should just react to changes! connect(docinfo, TQT_SIGNAL(completed(KileDocument::Info*)), m_ki->structureWidget(), TQT_SLOT(update(KileDocument::Info*))); KILE_DEBUG() << "createDocument: url " << doc->url() << " name " << doc->docName() << endl; KILE_DEBUG() << "createDocument: SANITY check: " << (docinfo->getDoc() == docFor(docinfo->url())) << endl; return doc; } Kate::View* Manager::loadItem(KileDocument::Type type, KileProjectItem *item, const TQString & text, bool openProjectItemViews) { Kate::View *view = 0L; KILE_DEBUG() << "==loadItem(" << item->url().path() << ")======" << endl; if ( item->type() != KileProjectItem::Image ) { view = loadText(type, TQString(), item->url(), item->encoding(), openProjectItemViews && item->isOpen(), item->highlight(), text); KILE_DEBUG() << "\tloadItem: docfor = " << docFor(item->url().path()) << endl; TextInfo *docinfo = textInfoFor(item->url().path()); item->setInfo(docinfo); KILE_DEBUG() << "\tloadItem: docinfo = " << docinfo << " doc = " << docinfo->getDoc() << " docfor = " << docFor(docinfo->url().path()) << endl; if ( docinfo->getDoc() != docFor(docinfo->url().path()) ) kdWarning() << "docinfo->getDoc() != docFor()" << endl; } else { KILE_DEBUG() << "\tloadItem: no document generated" << endl; TextInfo *docinfo = createTextDocumentInfo(m_ki->extensions()->determineDocumentType(item->url()), item->url()); item->setInfo(docinfo); if ( docFor(item->url()) == 0L) { docinfo->detach(); KILE_DEBUG() << "\t\t\tdetached" << endl; } } return view; } Kate::View* Manager::loadText(KileDocument::Type type, const TQString& name, const KURL &url , const TQString & encoding /* = TQString() */, bool create /* = true */, const TQString & highlight /* = TQString() */, const TQString & text /* = TQString() */, int index /* = - 1 */, const KURL& baseDirectory /* = KURL() */) { KILE_DEBUG() << "==loadText(" << url.url() << ")=================" << endl; //if doc already opened, update the structure view and return the view if ( !url.isEmpty() && m_ki->isOpen(url)) return m_ki->viewManager()->switchToTextView(url); TextInfo *docinfo = createTextDocumentInfo(type, url, baseDirectory); Kate::Document *doc = createDocument(name, url, docinfo, encoding, highlight); m_ki->structureWidget()->clean(docinfo); docinfo->updateStruct(); if ( !text.isNull() ) doc->setText(text); //FIXME: use signal/slot if (doc && create) return m_ki->viewManager()->createTextView(docinfo, index); KILE_DEBUG() << "just after createView()" << endl; KILE_DEBUG() << "\tdocinfo = " << docinfo << " doc = " << docinfo->getDoc() << " docfor = " << docFor(docinfo->url().path()) << endl; return 0L; } //FIXME: template stuff should be in own class Kate::View* Manager::loadTemplate(TemplateItem *sel) { TQString text = TQString(); if (sel && sel->name() != DEFAULT_EMPTY_CAPTION && sel->name() != DEFAULT_EMPTY_LATEX_CAPTION && sel->name() != DEFAULT_EMPTY_BIBTEX_CAPTION) { //create a new document to open the template in Kate::Document *tempdoc = (Kate::Document*) KTextEditor::createDocument ("libkatepart", this, "Kate::Document"); if (!tempdoc->openURL(KURL(sel->path()))) { KMessageBox::error(m_ki->parentWidget(), i18n("Could not find template: %1").arg(sel->name()),i18n("File Not Found")); } else { //substitute templates variables text = tempdoc->text(); delete tempdoc; replaceTemplateVariables(text); } } KileDocument::Type type = sel ? sel->type() : KileDocument::Undefined; //always set the base directory for scripts return createDocumentWithText(text, type, TQString(), (type == KileDocument::Script ? m_ki->scriptManager()->getLocalJScriptDirectory() : TQString())); } Kate::View* Manager::createDocumentWithText(const TQString& text, KileDocument::Type type /* = KileDocument::Undefined */, const TQString& extension, const KURL& baseDirectory) { Kate::View *view = loadText(type, KileUntitled::next() + (extension.isEmpty() ? TQString() : '.' + extension), KURL(), TQString(), true, TQString(), text, -1, baseDirectory); if (view) { //FIXME this shouldn't be necessary!!! view->getDoc()->setModified(true); newDocumentStatus(view->getDoc()); } return view; } Kate::View* Manager::createNewJScript() { Kate::View *view = createDocumentWithText(TQString(), Script, "js", m_ki->scriptManager()->getLocalJScriptDirectory()); emit(updateStructure(false, 0L)); emit(updateModeStatus()); return view; } Kate::View* Manager::createNewLaTeXDocument() { Kate::View *view = createDocumentWithText(TQString(), LaTeX); emit(updateStructure(false, 0L)); emit(updateModeStatus()); return view; } void Manager::replaceTemplateVariables(TQString &line) { line=line.replace("$$AUTHOR$$", KileConfig::author()); line=line.replace("$$DOCUMENTCLASSOPTIONS$$", KileConfig::documentClassOptions()); if (!KileConfig::templateEncoding().isEmpty()) { line=line.replace("$$INPUTENCODING$$", "\\usepackage["+ KileConfig::templateEncoding() +"]{inputenc}");} else { line = line.replace("$$INPUTENCODING$$","");} } void Manager::createTemplate() { Kate::View *view = m_ki->viewManager()->currentTextView(); if (view) { if (view->getDoc()->isModified() ) { KMessageBox::information(m_ki->parentWidget(),i18n("Please save the file first.")); return; } } else { KMessageBox::information(m_ki->parentWidget(),i18n("Open/create a document first.")); return; } KURL url = view->getDoc()->url(); KileDocument::Type type = m_ki->extensions()->determineDocumentType(url); if(type == KileDocument::Undefined || type == KileDocument::Text) { KMessageBox::information(m_ki->parentWidget(),i18n("Sorry, but a template for this type of document cannot be created.")); return; } ManageTemplatesDialog mtd(m_ki->templateManager(), url, i18n("Create Template From Document")); mtd.exec(); } void Manager::removeTemplate() { ManageTemplatesDialog mtd(m_ki->templateManager(), i18n("Remove Template")); mtd.exec(); } void Manager::fileNew() { NewFileWizard *nfw = new NewFileWizard(m_ki->templateManager(), m_ki->parentWidget()); if (nfw->exec()) { loadTemplate(nfw->getSelection()); if ( nfw->useWizard() ) emit ( startWizard() ); emit(updateStructure(false, 0L)); emit(updateModeStatus()); } delete nfw; } void Manager::fileNew(const KURL & url) { //create an empty file TQFile file(url.path()); file.open(IO_ReadWrite); file.close(); fileOpen(url, TQString()); } void Manager::fileOpen() { //determine the starting dir for the file dialog TQString compileName = m_ki->getCompileName(); TQString currentDir; if ( TQFileInfo(compileName).exists() ) currentDir = TQFileInfo(compileName).dirPath(true); else currentDir = m_ki->fileSelector()->dirOperator()->url().path(); // use a filter for fileOpen dialog Extensions *extensions = m_ki->extensions(); TQString filter = extensions->latexDocumentFileFilter() + '\n' + extensions->latexPackageFileFilter() + '\n' + extensions->bibtexFileFilter() + '\n' + extensions->metapostFileFilter() + '\n' + "*|" + i18n("All Files"); //get the URLs KEncodingFileDialog::Result result = KEncodingFileDialog::getOpenURLsAndEncoding( KileConfig::defaultEncoding(), currentDir, filter, m_ki->parentWidget(), i18n("Open Files") ); //open them KURL::List urls = result.URLs; for (KURL::List::Iterator i=urls.begin(); i != urls.end(); ++i) fileOpen(*i, result.encoding); } void Manager::fileSelected(const KFileItem *file) { fileSelected(file->url()); m_ki->fileSelector()->dirOperator()->view()->setSelected(file,false); } void Manager::fileSelected(const KileProjectItem * item) { fileOpen(item->url(), item->encoding()); } void Manager::fileSelected(const KURL & url) { fileOpen(url, m_ki->fileSelector()->comboEncoding()->lineEdit()->text()); } void Manager::saveURL(const KURL & url) { Kate::Document *doc = docFor(url); if (doc) doc->save(); } void Manager::newDocumentStatus(Kate::Document *doc) { KILE_DEBUG() << "void Manager::newDocumentStatus(Kate::Document)" << endl; if (doc == 0L) return; //sync terminal m_ki->texKonsole()->sync(); emit(documentStatusChanged(doc, doc->isModified(), 0)); //updatestructure if active document changed from modified to unmodified (typically after a save) if (!doc->isModified()) emit(updateStructure(true, textInfoFor(doc))); } void Manager::fileSaveAll(bool amAutoSaving, bool disUntitled ) { Kate::View *view= 0L; TQFileInfo fi; int saveResult = Kate::View::SAVE_ERROR; KURL url, backupUrl; KILE_DEBUG() << "===Kile::fileSaveAll(amAutoSaving = " << amAutoSaving << ",disUntitled = " << disUntitled <<")" << endl; for (uint i = 0; i < m_ki->viewManager()->textViews().count(); ++i) { view = m_ki->viewManager()->textView(i); if ( view && view->getDoc()->isModified() ) { url = view->getDoc()->url(); fi.setFile(url.path()); if ( ( !amAutoSaving && !(disUntitled && url.isEmpty() ) ) // DisregardUntitled is true and we have an untitled doc and don't autosave || ( amAutoSaving && !url.isEmpty() ) //don't save untitled documents when autosaving || ( !amAutoSaving && !disUntitled ) // both false, so we want to save everything ) { KILE_DEBUG() << "The files _" << autosaveWarnings.join(", ") << "_ have autosaveWarnings" < 0) // the size check ensures that we don't save empty files (to prevent something like #125809 in the future). { KURL backupUrl = KURL::fromPathOrURL(url.path()+ ".backup"); // patch for secure permissions, slightly modified for kile by Thomas Braun, taken from #103331 // get the right permissions, start with safe default mode_t perms = 0600; TDEIO::UDSEntry fentry; if (TDEIO::NetAccess::stat (url, fentry, kapp->mainWidget())) { KILE_DEBUG () << "stating successful: " << url.prettyURL() << endl; KFileItem item (fentry, url); perms = item.permissions(); } // first del existing file if any, than copy over the file we have // failure if a: the existing file could not be deleted, b: the file could not be copied if ( (!TDEIO::NetAccess::exists( backupUrl, false, kapp->mainWidget() ) || TDEIO::NetAccess::del( backupUrl, kapp->mainWidget() ) ) && TDEIO::NetAccess::file_copy( url, backupUrl, perms, true, false, kapp->mainWidget() ) ) { KILE_DEBUG()<<"backing up successful ("< "< "<save(); fi.refresh(); if(saveResult == Kate::View::SAVE_ERROR && fi.size() == 0 && !url.isEmpty()) // we probably hit bug #125809, inform the user of the possible consequences emit printMsg(KileTool::Error,i18n("Kile encountered problems while saving the file %1. Do you have enough free disk space left?").arg(url.url()),i18n("Saving")); } } } /* This may look superfluos but actually it is not, in the case of multiple modified docs it ensures that the structure view keeps synchronized with the currentTextView And if we only have one masterdoc or none nothing goes wrong. */ emit(updateStructure(false,NULL)); } void Manager::fileOpen(const KURL & url, const TQString & encoding, int index) { KILE_DEBUG() << "==Kile::fileOpen==========================" << endl; //don't want to receive signals from the fileselector since //that would allow the user to open a single file twice by double-clicking on it m_ki->fileSelector()->blockSignals(true); KILE_DEBUG() << "url is " << url.url() << endl; const KURL realurl = symlinkFreeURL(url); KILE_DEBUG() << "symlink free url is " << realurl.url() << endl; bool isopen = m_ki->isOpen(realurl); Kate::View *view = loadText(m_ki->extensions()->determineDocumentType(realurl), TQString(), realurl, encoding, true, TQString(), TQString(), index); KileProjectItem *item = itemFor(realurl); if(!isopen) { if(!item) emit addToProjectView(realurl); else if(view) view->setCursorPosition(item->lineNumber(),item->columnNumber()); } emit(updateStructure(true, 0L)); emit(updateModeStatus()); // update undefined references in this file emit(updateReferences(textInfoFor(realurl.path())) ); m_ki->fileSelector()->blockSignals(false); } void Manager::fileSave() { Kate::View* view = m_ki->viewManager()->currentTextView(); if(!view) { return; } KURL url = view->getDoc()->url(); if(url.isEmpty()) // newly created document { fileSaveAs(); return; } else { view->save(); } } void Manager::fileSaveAs(Kate::View* view) { if(!view) view = m_ki->viewManager()->currentTextView(); if(!view) return; Kate::Document* doc = view->getDoc(); Q_ASSERT(doc); KileDocument::TextInfo* info = textInfoFor(doc); Q_ASSERT(info); KURL startURL = info->url(); KURL oldURL = startURL; if(startURL.isEmpty()) { if((info->getBaseDirectory()).isEmpty()) { startURL = ":KILE_LATEX_SAVE_DIR"; } else { startURL = info->getBaseDirectory(); startURL.setFileName(doc->docName()); } } KILE_DEBUG() << "startURL is " << startURL.path() << endl; KEncodingFileDialog::Result result; KURL saveURL; while(true) { TQString filter = info->getFileFilter() + "\n* |" + i18n("All Files"); result = KEncodingFileDialog::getSaveURLAndEncoding(KileConfig::defaultEncoding(), startURL.url(), filter, m_ki->parentWidget(), i18n("Save File")); if(result.URLs.isEmpty() || result.URLs.first().isEmpty()) { return; } saveURL = result.URLs.first(); if(info->getType() == KileDocument::LaTeX) { saveURL = Info::makeValidTeXURL(saveURL, m_ki->extensions()->isTexFile(saveURL), false); // don't check for file existence } if(TDEIO::NetAccess::exists(saveURL, true, kapp->mainWidget())) // check for writing possibility { int r = KMessageBox::warningContinueCancel(m_ki->parentWidget(), i18n("A file with the name \"%1\" exists already. Do you want to overwrite it ?").arg(saveURL.fileName()), i18n("Overwrite File ?"), KGuiItem(i18n("&Overwrite")), TQString()); if(r != KMessageBox::Continue) { continue; } } break; } if(doc->encoding().lower() != result.encoding.lower()) { // save the document twice if the user has selected a different encoding; // this works around a bug in KatePart in the 'setEncoding' method, which // enforces a reload on every change of the encoding, and as a consequence the // user sees a document-modified dialog if(!doc->saveAs(saveURL)) { return; } doc->setEncoding(result.encoding); if(!doc->save()) { return; } } else { if(!doc->saveAs(saveURL)) { return; } } if(oldURL != saveURL) { if(info->isDocumentTypePromotionAllowed()) { recreateTextDocumentInfo(info); info = textInfoFor(doc); } m_ki->structureWidget()->updateUrl(info); emit addToRecentFiles(saveURL); emit addToProjectView(doc->url()); } } void Manager::fileSaveCopyAs() { Kate::Document *doc= m_ki->activeTextDocument(); Kate::View *view = 0L; if(doc) { KileDocument::TextInfo *originalInfo = textInfoFor(doc); if(!originalInfo) return; view = createDocumentWithText(doc->text(),originalInfo->getType()); KileDocument::TextInfo *newInfo = textInfoFor(view->getDoc()); if(originalInfo->url().isEmpty()) // untitled doc newInfo->setBaseDirectory(m_ki->fileSelector()->dirOperator()->url().path()); else newInfo->setBaseDirectory(originalInfo->url().path()); fileSaveAs(view); doc = view->getDoc(); if(doc && !doc->isModified()) // fileSaveAs was successful fileClose(doc); } } bool Manager::fileCloseAllOthers() { Kate::View * currentview = m_ki->viewManager()->currentTextView(); while ( m_ki->viewManager()->textViews().count() > 1 ) { Kate::View *view = m_ki->viewManager()->textViews().first(); if ( view == currentview ) view = m_ki->viewManager()->textViews().next(); if ( ! fileClose(view->getDoc()) ) return false; } return true; } bool Manager::fileCloseAll() { Kate::View * view = m_ki->viewManager()->currentTextView(); //assumes one view per doc here while( ! m_ki->viewManager()->textViews().isEmpty() ) { view = m_ki->viewManager()->textView(0); if (! fileClose(view->getDoc())) return false; } return true; } bool Manager::fileClose(const KURL & url) { Kate::Document *doc = docFor(url); if ( doc == 0L ) return true; else return fileClose(doc); } bool Manager::fileClose(Kate::Document *doc /* = 0L*/, bool closingproject /*= false*/) { KILE_DEBUG() << "==Kile::fileClose==========================" << endl; if (doc == 0L) doc = m_ki->activeTextDocument(); if (doc == 0L) return true; else //FIXME: remove from docinfo map, remove from dirwatch { KILE_DEBUG() << "doc->url().path()=" << doc->url().path() << endl; const KURL url = doc->url(); TextInfo *docinfo= textInfoFor(doc); if (docinfo == 0L) { kdWarning() << "no DOCINFO for " << url.url() << endl; return true; } KileProjectItemList *items = itemsFor(docinfo); while ( items->current() ) { //FIXME: refactor here if (items->current() && doc) storeProjectItem(items->current(),doc); items->next(); } delete items; if ( doc->closeURL() ) { // docinfo may have been recreated from 'Untitled' doc to a named doc if ( url.isEmpty() ) docinfo= textInfoFor(doc); if ( KileConfig::cleanUpAfterClose() ) cleanUpTempFiles(url, true); // yes we pass here url and not docinfo->url() //FIXME: use signal/slot m_ki->viewManager()->removeView(static_cast(doc->views().first())); //remove the decorations trashDoc(docinfo, doc); m_ki->structureWidget()->clean(docinfo); removeTextDocumentInfo(docinfo, closingproject); emit removeFromProjectView(url); emit updateModeStatus(); } else return false; } return true; } void Manager::buildProjectTree(const KURL & url) { KileProject * project = projectFor(url); if (project) buildProjectTree(project); } void Manager::buildProjectTree(KileProject *project) { if (project == 0) project = activeProject(); if (project == 0 ) project = selectProject(i18n("Refresh Project Tree")); if (project) { //TODO: update structure for all docs project->buildProjectTree(); } else if (m_projects.count() == 0) KMessageBox::error(m_ki->parentWidget(), i18n("The current document is not associated to a project. Please activate a document that is associated to the project you want to build the tree for, then choose Refresh Project Tree again."),i18n( "Could Not Refresh Project Tree")); } void Manager::projectNew() { KILE_DEBUG() << "==Kile::projectNew==========================" << endl; KileNewProjectDlg *dlg = new KileNewProjectDlg(m_ki->templateManager(), m_ki->extensions(), m_ki->parentWidget()); KILE_DEBUG()<< "\tdialog created" << endl; if (dlg->exec()) { KILE_DEBUG()<< "\tdialog executed" << endl; KILE_DEBUG() << "\t" << dlg->name() << " " << dlg->location() << endl; KileProject *project = dlg->project(); //add the project file to the project //TODO: shell expand the filename KileProjectItem *item = new KileProjectItem(project, project->url()); item->setOpenState(false); projectOpenItem(item); if (dlg->createNewFile()) { TQString filename = dlg->file(); //create the new document and fill it with the template //TODO: shell expand the filename Kate::View *view = loadTemplate(dlg->getSelection()); //derive the URL from the base url of the project KURL url = project->baseURL(); url.addPath(filename); TextInfo *docinfo = textInfoFor(view->getDoc()); //save the new file view->getDoc()->saveAs(url); emit documentStatusChanged(view->getDoc(), false, 0); //add this file to the project item = new KileProjectItem(project, url); //project->add(item); mapItem(docinfo, item); //docinfo->updateStruct(m_kwStructure->level()); emit(updateStructure(true, docinfo)); } project->buildProjectTree(); //project->save(); addProject(project); emit(updateModeStatus()); emit(addToRecentProjects(project->url())); } } void Manager::addProject(const KileProject *project) { KILE_DEBUG() << "==void Manager::addProject(const KileProject *project)==========" << endl; m_projects.append(project); KILE_DEBUG() << "\tnow " << m_projects.count() << " projects" << endl; emit addToProjectView(project); connect(project, TQT_SIGNAL(projectTreeChanged(const KileProject *)), this, TQT_SIGNAL(projectTreeChanged(const KileProject *))); } KileProject* Manager::selectProject(const TQString& caption) { TQStringList list; TQPtrListIterator it(m_projects); while (it.current()) { list.append((*it)->name()); ++it; } KileProject *project = 0; TQString name = TQString(); if (list.count() > 1) { KileListSelector *dlg = new KileListSelector(list, caption, i18n("Select Project"), m_ki->parentWidget()); if (dlg->exec()) { name = list[dlg->currentItem()]; } delete dlg; } else if (list.count() == 0) { return 0; } else name = m_projects.first()->name(); project = projectFor(name); return project; } void Manager::addToProject(const KURL & url) { KILE_DEBUG() << "===Kile::addToProject(const KURL & url =" << url.url() << ")" << endl; KileProject *project = selectProject(i18n("Add to Project")); if (project) addToProject(project, url); } void Manager::addToProject(KileProject* project, const KURL & url) { const KURL realurl = symlinkFreeURL(url); TQFileInfo fi(realurl.path()); if (project->contains(realurl)) { emit printMsg(KileTool::Info,i18n("The file %1 is already member of the project %2").arg(realurl.filename()).arg(project->name()),i18n("Add to Project")); return; } else if(!fi.exists() || !fi.isReadable()) { emit printMsg( KileTool::Info,i18n("The file %1 can not be added because it does not exist or is not readable").arg(realurl.filename()),i18n("Add to Project")); return; } KileProjectItem *item = new KileProjectItem(project, realurl); item->setOpenState(m_ki->isOpen(realurl)); projectOpenItem(item); emit addToProjectView(item); buildProjectTree(project); } void Manager::removeFromProject(const KileProjectItem *item) { if (item && item->project()) { KILE_DEBUG() << "\tprojecturl = " << item->project()->url().path() << ", url = " << item->url().path() << endl; if (item->project()->url() == item->url()) { KMessageBox::error(m_ki->parentWidget(), i18n("This file is the project file, it holds all the information about your project. Therefore it is not allowed to remove this file from its project."), i18n("Cannot Remove File From Project")); return; } emit removeItemFromProjectView(item, m_ki->isOpen(item->url())); KileProject *project = item->project(); item->project()->remove(item); // update undefined references in all project files updateProjectReferences(project); project->buildProjectTree(); } } void Manager::projectOpenItem(KileProjectItem *item, bool openProjectItemViews) { KILE_DEBUG() << "==Kile::projectOpenItem==========================" << endl; KILE_DEBUG() << "\titem:" << item->url().path() << endl; if (m_ki->isOpen(item->url())) //remove item from projectview (this file was opened before as a normal file) emit removeFromProjectView(item->url()); Kate::View *view = loadItem(m_ki->extensions()->determineDocumentType(item->url()), item, TQString(), openProjectItemViews); if ( (!item->isOpen()) && (view == 0L) && (item->getInfo()) ) //doc shouldn't be displayed, trash the doc trashDoc(item->getInfo()); else if (view != 0L) view->setCursorPosition(item->lineNumber(), item->columnNumber()); //oops, doc apparently was open while the project settings wants it closed, don't trash it the doc, update openstate instead if ((!item->isOpen()) && (view != 0L)) item->setOpenState(true); } KileProject* Manager::projectOpen(const KURL & url, int step, int max, bool openProjectItemViews) { KILE_DEBUG() << "==Kile::projectOpen==========================" << endl; KILE_DEBUG() << "\tfilename: " << url.fileName() << endl; const KURL realurl = symlinkFreeURL(url); if (m_ki->projectIsOpen(realurl)) { m_kpd->cancel(); KMessageBox::information(m_ki->parentWidget(), i18n("The project you tried to open is already opened. If you wanted to reload the project, close the project before you re-open it."),i18n("Project Already Open")); return 0L; } TQFileInfo fi(realurl.path()); if ( ! fi.isReadable() ) { m_kpd->cancel(); if (KMessageBox::warningYesNo(m_ki->parentWidget(), i18n("The project file for this project does not exists or is not readable. Remove this project from the recent projects list?"),i18n("Could Not Load Project File")) == KMessageBox::Yes) emit(removeFromRecentProjects(realurl)); return 0L; } m_kpd->show(); KileProject *kp = new KileProject(realurl,m_ki->extensions()); if(kp->isInvalid()) { m_kpd->cancel(); delete kp; return 0L; } emit(addToRecentProjects(realurl)); KileProjectItemList *list = kp->items(); int project_steps = list->count() + 1; m_kpd->progressBar()->setTotalSteps(project_steps * max); project_steps *= step; m_kpd->progressBar()->setValue(project_steps); // open the project files in the correct order TQValueVector givenPositionVector(list->count(), NULL); TQValueList notCorrectlyOrderedList; for(KileProjectItem *item = list->first(); item; item = list->next()) { int order = item->order(); if(order >= 0 && static_cast(order) >= list->count()) { order = -1; } if(!item->isOpen() || order < 0 || givenPositionVector[order] != NULL) { notCorrectlyOrderedList.push_back(item); } else { givenPositionVector[order] = item; } } TQValueList orderedList; for(unsigned int i = 0; i < givenPositionVector.size(); ++i) { KileProjectItem *item = givenPositionVector[i]; if(item) { orderedList.push_back(item); } } for(TQValueList::iterator i = notCorrectlyOrderedList.begin(); i != notCorrectlyOrderedList.end(); ++i) { orderedList.push_back(*i); } unsigned int counter = 0; for (TQValueList::iterator i = orderedList.begin(); i != orderedList.end(); ++i) { projectOpenItem(*i, openProjectItemViews); m_kpd->progressBar()->setValue(counter + project_steps); kapp->processEvents(); ++counter; } kp->buildProjectTree(); addProject(kp); emit(updateStructure(false, 0L)); emit(updateModeStatus()); // update undefined references in all project files updateProjectReferences(kp); if (step == (max - 1)) m_kpd->cancel(); m_ki->viewManager()->switchToTextView(kp->lastDocument()); return kp; } // as all labels are gathered in the project, we can check for unsolved references void Manager::updateProjectReferences(KileProject *project) { KileProjectItemList *list = project->items(); for ( uint i=0; i < list->count(); ++i) { emit(updateReferences(list->at(i)->getInfo())); } } KileProject* Manager::projectOpen() { KILE_DEBUG() << "==Kile::projectOpen==========================" << endl; KURL url = KFileDialog::getOpenURL( KileConfig::defaultProjectLocation(), i18n("*.kilepr|Kile Project Files\n*|All Files"), m_ki->parentWidget(), i18n("Open Project") ); if (!url.isEmpty()) return projectOpen(url); else return 0L; } void Manager::projectSave(KileProject *project /* = 0 */) { KILE_DEBUG() << "==Kile::projectSave==========================" << endl; if (project == 0) { //find the project that corresponds to the active doc project= activeProject(); } if (project == 0 ) project = selectProject(i18n("Save Project")); if (project) { KileProjectItemList *list = project->items(); Kate::Document *doc = NULL; KileProjectItem *item = NULL; TextInfo *docinfo = NULL; // determine the order in which the project items are opened TQValueVector viewPositionVector(m_ki->viewManager()->getTabCount(), NULL); for (KileProjectItemList::iterator i = list->begin(); i != list->end(); ++i) { docinfo = (*i)->getInfo(); if(docinfo) { Kate::View *view = m_ki->viewManager()->textView(docinfo); if(view) { int position = m_ki->viewManager()->getIndexOf(view); if(position >= 0 && static_cast(position) < viewPositionVector.size()) { viewPositionVector[position] = *i; } } } } int position = 0; for(unsigned int i = 0; i < viewPositionVector.size(); ++i) { if(viewPositionVector[i] != NULL) { viewPositionVector[i]->setOrder(position); ++position; } } //update the open-state of the items for (KileProjectItemList::iterator i = list->begin(); i != list->end(); ++i) { item = *i; KILE_DEBUG() << "\tsetOpenState(" << (*i)->url().path() << ") to " << m_ki->isOpen(item->url()) << endl; item->setOpenState(m_ki->isOpen(item->url())); docinfo = item->getInfo(); if (docinfo != 0L) doc = docinfo->getDoc(); if (doc != 0L) storeProjectItem(item, doc); doc = 0L; docinfo = 0L; } project->save(); } else KMessageBox::error(m_ki->parentWidget(), i18n("The current document is not associated to a project. Please activate a document that is associated to the project you want to save, then choose Save Project again."),i18n( "Could Determine Active Project")); } void Manager::projectAddFiles(const KURL & url) { KileProject *project = projectFor(url); if (project) projectAddFiles(project,url); } void Manager::projectAddFiles(KileProject *project,const KURL & fileUrl) { KILE_DEBUG() << "==Kile::projectAddFiles()==========================" << endl; if (project == 0 ) project = activeProject(); if (project == 0 ) project = selectProject(i18n("Add Files to Project")); if (project) { TQString currentDir; if(fileUrl.isEmpty()) currentDir=project->url().directory(); else currentDir=fileUrl.directory(); KILE_DEBUG() << "currentDir is " << currentDir << endl; KFileDialog *dlg = new KFileDialog(currentDir, i18n("*|All Files"),m_ki->parentWidget(), 0, true ); KPushButton* okButton = dlg->okButton(); okButton->setText(i18n("Add")); dlg->setCaption(i18n("Add Files")); KFile::Mode mode = static_cast( KFile::Files | KFile::ExistingOnly); dlg->setMode(mode); if(dlg->exec()) { KURL::List urls = dlg->selectedURLs(); for (uint i=0; i < urls.count(); ++i) { addToProject(project, urls[i]); } // update undefined references in all project files updateProjectReferences(project); } delete dlg; //open them } else if (m_projects.count() == 0) KMessageBox::error(m_ki->parentWidget(), i18n("There are no projects opened. Please open the project you want to add files to, then choose Add Files again."),i18n( "Could Not Determine Active Project")); } void Manager::toggleArchive(KileProjectItem *item) { item->setArchive(!item->archive()); } void Manager::projectOptions(const KURL & url) { KileProject *project = projectFor(url); if (project) projectOptions(project); } void Manager::projectOptions(KileProject *project /* = 0*/) { KILE_DEBUG() << "==Kile::projectOptions==========================" << endl; if (project ==0 ) project = activeProject(); if (project == 0 ) project = selectProject(i18n("Project Options For")); if (project) { KILE_DEBUG() << "\t" << project->name() << endl; KileProjectOptionsDlg *dlg = new KileProjectOptionsDlg(project, m_ki->extensions(), m_ki->parentWidget()); dlg->exec(); } else if (m_projects.count() == 0) KMessageBox::error(m_ki->parentWidget(), i18n("The current document is not associated to a project. Please activate a document that is associated to the project you want to modify, then choose Project Options again."),i18n( "Could Not Determine Active Project")); } bool Manager::projectCloseAll() { KILE_DEBUG() << "==Kile::projectCloseAll==========================" << endl; bool close = true; TQPtrListIterator it(m_projects); int i = m_projects.count() + 1; while ( it.current() && close && (i > 0)) { close = close && projectClose(it.current()->url()); --i; } return close; } bool Manager::projectClose(const KURL & url) { KILE_DEBUG() << "==Kile::projectClose==========================" << endl; KileProject *project = 0; if (url.isEmpty()) { project = activeProject(); if (project == 0 ) project = selectProject(i18n("Close Project")); } else { project = projectFor(url); } if (project) { KILE_DEBUG() << "\tclosing:" << project->name() << endl; project->setLastDocument(m_ki->getName()); projectSave(project); KileProjectItemList *list = project->items(); bool close = true; Kate::Document *doc = 0L; TextInfo *docinfo = 0L; for (uint i =0; i < list->count(); ++i) { doc = 0L; docinfo = list->at(i)->getInfo(); if (docinfo) { doc = docinfo->getDoc(); } else { continue; } if (doc) { KILE_DEBUG() << "\t\tclosing item " << doc->url().path() << endl; bool r = fileClose(doc, true); close = close && r; if (!close) break; } else { // we still need to delete the TextInfo object removeTextDocumentInfo(docinfo, true); } } if (close) { m_projects.remove(project); emit removeFromProjectView(project); delete project; emit(updateModeStatus()); return true; } else return false; } else if (m_projects.count() == 0) KMessageBox::error(m_ki->parentWidget(), i18n("The current document is not associated to a project. Please activate a document that is associated to the project you want to close, then choose Close Project again."),i18n( "Could Not Close Project")); return true; } void Manager::storeProjectItem(KileProjectItem *item, Kate::Document *doc) { KILE_DEBUG() << "===Kile::storeProjectItem==============" << endl; KILE_DEBUG() << "\titem = " << item << ", doc = " << doc << endl; item->setEncoding(doc->encoding()); item->setHighlight(doc->hlModeName(doc->hlMode())); uint l = 0, c = 0; TQPtrList viewList = doc->views(); if(!viewList.isEmpty()) { Kate::View *view = static_cast(viewList.first()); if(view) { view->cursorPosition(&l,&c); } } item->setLineNumber(l); item->setColumnNumber(c); KILE_DEBUG() << "\t" << item->encoding() << " " << item->highlight() << " should be " << doc->hlModeName(doc->hlMode()) << endl; } void Manager::cleanUpTempFiles(const KURL &url, bool silent) { KILE_DEBUG() << "===void Manager::cleanUpTempFiles(const KURL " << url.path() << ", bool " << silent << ")===" << endl; if( url.isEmpty() ) return; TQStringList extlist; TQFileInfo fi(url.path()); const TQStringList templist = TQStringList::split(" ", KileConfig::cleanUpFileExtensions()); const TQString fileName = fi.fileName(); const TQString dirPath = fi.dirPath(true); const TQString baseName = fi.baseName(true); for (uint i=0; i < templist.count(); ++i) { fi.setFile( dirPath + '/' + baseName + templist[i] ); if ( fi.exists() ) extlist.append(templist[i]); } if (!silent && ( KileUntitled::isUntitled(fileName) || fileName.isEmpty() ) ) return; if (!silent && extlist.count() > 0 ) { KILE_DEBUG() << "not silent" << endl; KileDialog::Clean *dialog = new KileDialog::Clean(m_ki->parentWidget(), fileName, extlist); if ( dialog->exec() ) extlist = dialog->getCleanlist(); else { delete dialog; return; } delete dialog; } if ( extlist.count() == 0 ) emit printMsg(KileTool::Warning, i18n("Nothing to clean for %1").arg(fileName), i18n("Clean")); else { for ( uint i = 0 ; i < extlist.count() ; ++i ) { TQFile file( dirPath + '/' + baseName + extlist[i] ); KILE_DEBUG() << "About to remove file = " << file.name() << endl; file.remove(); } emit printMsg(KileTool::Info, i18n("Cleaning %1 : %2").arg(fileName).arg(extlist.join(" ")), i18n("Clean")); } } void Manager::openDroppedURLs(TQDropEvent *e) { KURL::List urls; Extensions *extensions = m_ki->extensions(); if(KURLDrag::decode(e, urls)) { for(KURL::List::iterator i = urls.begin(); i != urls.end(); ++i) { KURL url = *i; if(extensions->isProjectFile(url)) { projectOpen(url); } else { fileOpen(url); } } } } // Show all opened projects and switch to another one, if you want void Manager::projectShow() { if ( m_projects.count() <= 1 ) return; // select the new project KileProject *project = selectProject(i18n("Switch Project")); if ( !project || project==activeProject() ) return; // get last opened document const KURL lastdoc = project->lastDocument(); KileProjectItem *docitem = ( !lastdoc.isEmpty() ) ? itemFor(lastdoc,project) : 0L; // if not, we search for the first opened tex file of this project // if no file is opened, we take the first tex file mentioned in the list KileProjectItem *first_texitem = 0L; if ( ! docitem ) { KileProjectItemList *list = project->items(); for ( KileProjectItem *item=list->first(); item; item=list->next() ) { TQString itempath = item->path(); // called from TDEAction 'Show projects...': find the first opened // LaTeX document or, if that fails, any other opened file TQStringList extlist = TQStringList::split(" ",m_ki->extensions()->latexDocuments() + ' ' + m_ki->extensions()->latexPackages()); for ( TQStringList::Iterator it=extlist.begin(); it!=extlist.end(); ++it ) { if ( itempath.find( (*it), -(*it).length() ) >= 0 ) { if ( m_ki->isOpen(item->url()) ) { docitem = item; break; } else if ( ! first_texitem ) first_texitem = item; } } if ( docitem ) break; } } // did we find one opened file or must we take the first entry if ( ! docitem ) { if ( ! first_texitem ) return; docitem = first_texitem; } // ok, we can switch to another project now if ( m_ki->isOpen(docitem->url()) ) m_ki->viewManager()->switchToTextView(docitem->url()); else fileOpen( docitem->url(),docitem->encoding() ); } void Manager::projectRemoveFiles() { KileProjectItemList* items = selectProjectFileItems( i18n("Select Files to Remove") ); if ( items && items->count() > 0 ) for ( KileProjectItemList::Iterator it = items->begin(); it != items->end(); ++it ) removeFromProject(*it); delete items; } void Manager::projectShowFiles() { KileProjectItem *item = selectProjectFileItem( i18n("Select File") ); if ( item ) { if ( item->type() == KileProjectItem::ProjectFile ) dontOpenWarning( item, i18n("Show Project Files"), i18n("project configuration file") ); else if ( item->type() == KileProjectItem::Image ) dontOpenWarning( item, i18n("Show Project Files"), i18n("graphics file") ); else { // ok, we can switch to another file if ( m_ki->isOpen(item->url()) ) m_ki->viewManager()->switchToTextView(item->url()); else fileOpen( item->url(),item->encoding() ); } } } void Manager::projectOpenAllFiles() { KileProject *project = selectProject(i18n("Select Project")); if (project != 0L) { projectOpenAllFiles(project->url()); } } void Manager::projectOpenAllFiles(const KURL & url) { KileProject* project; Kate::Document* doc = 0L; if(!url.isValid()) return; project = projectFor(url); if(!project) return; if(m_ki->viewManager()->currentTextView()) doc = m_ki->viewManager()->currentTextView()->getDoc(); // we remember the actual view, so the user gets the same view back after opening KileProjectItemList *list = project->items(); for ( KileProjectItem *item=list->first(); item; item = list->next() ) { if ( item->type()==KileProjectItem::ProjectFile ) dontOpenWarning( item, i18n("Open All Project Files"), i18n("project configuration file") ); else if ( item->type()==KileProjectItem::Image ) dontOpenWarning( item, i18n("Open All Project Files"), i18n("graphics file") ); else if ( ! m_ki->isOpen(item->url()) ) fileOpen( item->url(),item->encoding() ); } if(doc) // we have a doc so switch back to original view m_ki->viewManager()->switchToTextView(doc->url()); } TQStringList Manager::getProjectFiles() { TQStringList filelist; KileProject *project = activeProject(); if ( project ) { KileProjectItemList *list = project->items(); for ( KileProjectItem *item=list->first(); item; item = list->next() ) { if ( item->type()!=KileProjectItem::ProjectFile && item->type()!=KileProjectItem::Image ) filelist << item->url().path(); } } return filelist; } void Manager::dontOpenWarning(KileProjectItem *item, const TQString &action, const TQString &filetype) { emit printMsg(KileTool::Info, i18n("not opened: %1 (%2)").arg(item->url().path()).arg(filetype), action); } KileProjectItem* Manager::selectProjectFileItem(const TQString &label) { // select a project KileProject *project = selectProject(i18n("Select Project")); if ( ! project ) return 0L; // get a list of files TQStringList filelist; TQMap map; KileProjectItemList *list = project->items(); for ( KileProjectItem *item=list->first(); item; item = list->next() ) { filelist << item->path(); map[item->path()] = item; } // select one of these files KileProjectItem *item = 0L; KileListSelector *dlg = new KileListSelector(filelist,i18n("Project Files"),label, m_ki->parentWidget()); if ( dlg->exec() ) { if ( dlg->currentItem() >= 0 ) { TQString name = filelist[dlg->currentItem()]; if ( map.contains(name) ) item = map[name]; else KMessageBox::error(m_ki->parentWidget(), i18n("Could not determine the selected file."),i18n( "Project Error")); } } delete dlg; return item; } KileProjectItemList* Manager::selectProjectFileItems(const TQString &label) { KileProject *project = selectProject(i18n("Select Project")); if ( ! project ) return 0L; TQStringList filelist, selectedfiles; TQMap map; KileProjectItemList *list = project->items(); for ( KileProjectItem *item=list->first(); item; item = list->next() ) { filelist << item->path(); map[item->path()] = item; } KileProjectItemList *items = new KileProjectItemList(); items->setAutoDelete(false); KileListSelectorMultiple *dlg = new KileListSelectorMultiple(filelist,i18n("Project Files"),label, m_ki->parentWidget()); if ( dlg->exec() ) { if ( dlg->currentItem() >= 0 ) { selectedfiles = dlg->selected(); for ( TQStringList::Iterator it = selectedfiles.begin(); it != selectedfiles.end(); ++it ){ if ( map.contains(*it) ) items->append( map[(*it)] ); else KMessageBox::error(m_ki->parentWidget(), i18n("Could not determine the selected file."),i18n( "Project Error")); } } } delete dlg; return items; } // add a new file to the project // - only when there is an active project // - if the file doesn't already belong to it (checked by addToProject) void Manager::projectAddFile(TQString filename, bool graphics) { KILE_DEBUG() << "===Kile::projectAddFile==============" << endl; KileProject *project = activeProject(); if ( ! project ) return; TQFileInfo fi(filename); if ( ! fi.exists() ) { if ( graphics ) return; // called from InputDialog after a \input- or \include command: // - if the chosen file has an extension: accept // - if not we add the default TeX extension: accept if it exists else reject TQString ext = fi.extension(); if ( ! ext.isEmpty() ) return; filename += m_ki->extensions()->latexDocumentDefault(); if ( TQFileInfo(filename).exists() ) return; } //ok, we have a project and an existing file KILE_DEBUG() << "\tadd file: " << filename << endl; m_ki->viewManager()->updateStructure(true); KURL url; url.setPath(filename); addToProject(project, url); } const KURL Manager::symlinkFreeURL(const KURL& url) { KILE_DEBUG() << "===symlinkFreeURL==" << endl; if( !url.isLocalFile() ) return url; TQDir dir(url.directory()); TQString filename=url.path(); // if the directory does not exist we return the old url (just to be sure) if(dir.exists()) filename= dir.canonicalPath() + '/' + url.filename(); else KILE_DEBUG() << "directory " << url.directory() << "does not exist" << endl; return KURL::fromPathOrURL(filename); } void Manager::cleanupDocumentInfoForProjectItems(KileDocument::Info *info) { KileProjectItemList *itms = itemsFor(info); TQPtrListIterator it(*itms); KileProjectItem *current; while((current = it.current()) != 0) { ++it; current->setInfo(0); } delete itms; } } #include "kiledocmanager.moc"