/*************************************************************************** * Copyright (C) 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 "circuitdocument.h" #include "docmanager.h" #include "docmanageriface.h" #include "flowcodedocument.h" #include "iteminterface.h" #include "itemselector.h" #include "ktechlab.h" #include "core/ktlconfig.h" #include "mechanicsdocument.h" #include "textdocument.h" #include "textview.h" #include "viewcontainer.h" #include #include #include #include #include DocManager * DocManager::m_pSelf = 0l; DocManager * DocManager::self( KTechlab * ktechlab ) { if ( !m_pSelf ) { assert(ktechlab); m_pSelf = new DocManager(ktechlab); } return m_pSelf; } DocManager::DocManager( KTechlab * ktechlab ) : TQObject( ktechlab ), p_ktechlab(ktechlab) { p_focusedView = 0l; m_countCircuit = 0; m_countFlowCode = 0; m_countMechanics = 0; m_countOther = 0; p_connectedDocument = 0l; m_nextDocumentID = 1; m_pIface = new DocManagerIface(this); } DocManager::~DocManager() { } bool DocManager::closeAll() { const DocumentList::iterator end = m_documentList.end(); while ( !m_documentList.isEmpty() ) { Document *document = m_documentList.first(); if ( document->fileClose() ) { m_documentList.remove(document); removeDocumentAssociations(document); } else return false; } return true; } void DocManager::gotoTextLine( const KURL &url, int line ) { TextDocument * doc = dynamic_cast( openURL(url) ); if (!doc) return; doc->textView()->gotoLine(line); } Document* DocManager::openURL( const KURL &url, ViewArea *viewArea ) { if ( url.isEmpty() ) return 0l; if ( url.isLocalFile() ) { TQFile file(url.path()); if ( file.open(IO_ReadOnly) == false ) { KMessageBox::sorry( 0l, i18n("Could not open '%1'").arg( url.prettyURL() ) ); return 0l; } file.close(); } // If the document is already open, and a specific view area hasn't been // specified, then just return that document - otherwise, create a new // view in the viewarea Document *document = findDocument(url); if ( document ) { if ( viewArea ) createNewView( document, viewArea ); else giveDocumentFocus( document, viewArea ); return document; } TQString fileName = url.fileName(); TQString extension = fileName.right( fileName.length() - fileName.findRev('.') ); if ( extension == ".circuit" ) return openCircuitFile( url, viewArea ); else if ( extension == ".flowcode" ) return openFlowCodeFile( url, viewArea ); else if ( extension == ".mechanics" ) return openMechanicsFile( url, viewArea ); else return openTextFile( url, viewArea ); } Document *DocManager::getFocusedDocument() const { Document * doc = p_focusedView ? p_focusedView->document() : 0l; return (doc && !doc->isDeleted()) ? doc : 0l; } void DocManager::giveDocumentFocus( Document * toFocus, ViewArea * viewAreaForNew ) { if ( !toFocus ) return; if ( View * activeView = toFocus->activeView() ) { p_ktechlab->tabWidget()->showPage( activeView->viewContainer() ); activeView->setFocused(); activeView->viewContainer()->setFocused(); } else if ( viewAreaForNew ) createNewView( toFocus, viewAreaForNew ); } TQString DocManager::untitledName( int type ) { TQString name; switch(type) { case Document::dt_circuit: { if ( m_countCircuit>1 ) name = i18n("Untitled (Circuit %1)").arg(TQString::number(m_countCircuit)); else name = i18n("Untitled (Circuit)"); m_countCircuit++; break; } case Document::dt_flowcode: { if ( m_countFlowCode>1 ) name = i18n("Untitled (FlowCode %1)").arg(TQString::number(m_countFlowCode)); else name = i18n("Untitled (FlowCode)"); m_countFlowCode++; break; } case Document::dt_mechanics: { if ( m_countMechanics>1 ) name = i18n("Untitled (Mechanics %1)").arg(TQString::number(m_countMechanics)); else name = i18n("Untitled (Mechanics)"); m_countMechanics++; break; } default: { if ( m_countOther>1 ) name = i18n("Untitled (%1)").arg(TQString::number(m_countOther)); else name = i18n("Untitled"); m_countOther++; break; } } return name; } Document *DocManager::findDocument( const KURL &url ) const { // First, look in the associated documents if ( m_associatedDocuments.contains(url) ) return m_associatedDocuments[url]; // Not found, so look in the known documents const DocumentList::const_iterator end = m_documentList.end(); for ( DocumentList::const_iterator it = m_documentList.begin(); it != end; ++it ) { if ( (*it)->url() == url ) return *it; } return 0l; } void DocManager::associateDocument( const KURL &url, Document *document ) { if (!document) return; m_associatedDocuments[url] = document; } void DocManager::removeDocumentAssociations( Document *document ) { bool doneErase; do { doneErase = false; const URLDocumentMap::iterator end = m_associatedDocuments.end(); for ( URLDocumentMap::iterator it = m_associatedDocuments.begin(); it != end; ++it ) { if ( it.data() == document ) { doneErase = true; m_associatedDocuments.erase(it); break; } } } while (doneErase); } void DocManager::handleNewDocument( Document *document, ViewArea *viewArea ) { if ( !document || m_documentList.contains(document) ) return; m_documentList.append(document); document->setDCOPID(m_nextDocumentID++); connect( document, TQT_SIGNAL(modifiedStateChanged()), p_ktechlab, TQT_SLOT(slotDocModifiedChanged()) ); connect( document, TQT_SIGNAL(fileNameChanged(const KURL&)), p_ktechlab, TQT_SLOT(slotDocModifiedChanged()) ); connect( document, TQT_SIGNAL(fileNameChanged(const KURL&)), p_ktechlab, TQT_SLOT(addRecentFile(const KURL&)) ); connect( document, TQT_SIGNAL(destroyed(TQObject* )), this, TQT_SLOT(documentDestroyed(TQObject* )) ); connect( document, TQT_SIGNAL(viewFocused(View* )), this, TQT_SLOT(slotViewFocused(View* )) ); connect( document, TQT_SIGNAL(viewUnfocused()), this, TQT_SLOT(slotViewUnfocused()) ); createNewView( document, viewArea ); } View *DocManager::createNewView( Document *document, ViewArea *viewArea ) { if (!document) return 0l; View *view = 0l; if (viewArea) view = document->createView( viewArea->viewContainer(), viewArea->id() ); else { ViewContainer *viewContainer = new ViewContainer( document->caption(), p_ktechlab ); view = document->createView( viewContainer, 0 ); p_ktechlab->addWindow(viewContainer); } view->setFocused(); return view; } void DocManager::documentDestroyed( TQObject *obj ) { Document *doc = static_cast(obj); m_documentList.remove(doc); removeDocumentAssociations(doc); disableContextActions(); } void DocManager::slotViewFocused( View *view ) { ViewContainer * vc = static_cast(p_ktechlab->tabWidget()->currentPage()); if (!vc) view = 0l; if (!view) return; // This function can get called with a view that is not in the current view // container (such as when the user right clicks and then the popup is // destroyed - not too sure why, but this is the easiest way to fix it). if ( view->viewContainer() != vc ) view = vc->activeView(); if ( !view || (View*)p_focusedView == view ) return; if (p_focusedView) slotViewUnfocused(); p_focusedView = view; if ( TextView * textView = dynamic_cast((View*)p_focusedView) ) p_ktechlab->factory()->addClient( textView->kateView() ); else p_ktechlab->factory()->addClient( p_focusedView ); Document *document = view->document(); connect( document, TQT_SIGNAL(undoRedoStateChanged()), p_ktechlab, TQT_SLOT(slotDocUndoRedoChanged()) ); p_connectedDocument = document; if ( document->type() == Document::dt_circuit || document->type() == Document::dt_flowcode || document->type() == Document::dt_mechanics ) { ItemDocument *cvb = static_cast(view->document()); ItemInterface::self()->slotItemDocumentChanged(cvb); } p_ktechlab->slotDocUndoRedoChanged(); p_ktechlab->slotDocModifiedChanged(); p_ktechlab->requestUpdateCaptions(); } void DocManager::slotViewUnfocused() { p_ktechlab->removeGUIClients(); disableContextActions(); if (!p_focusedView) return; if (p_connectedDocument) { disconnect( p_connectedDocument, TQT_SIGNAL(undoRedoStateChanged()), p_ktechlab, TQT_SLOT(slotDocUndoRedoChanged()) ); p_connectedDocument = 0l; } ItemInterface::self()->slotItemDocumentChanged(0l); p_focusedView = 0l; // p_ktechlab->setCaption( 0 ); p_ktechlab->requestUpdateCaptions(); } void DocManager::disableContextActions() { p_ktechlab->action("file_save")->setEnabled(false); p_ktechlab->action("file_save_as")->setEnabled(false); p_ktechlab->action("file_close")->setEnabled(false); p_ktechlab->action("file_print")->setEnabled(false); p_ktechlab->action("edit_undo")->setEnabled(false); p_ktechlab->action("edit_redo")->setEnabled(false); p_ktechlab->action("edit_cut")->setEnabled(false); p_ktechlab->action("edit_copy")->setEnabled(false); p_ktechlab->action("edit_paste")->setEnabled(false); p_ktechlab->action("view_split_leftright")->setEnabled(false); p_ktechlab->action("view_split_topbottom")->setEnabled(false); } TextDocument *DocManager::createTextDocument() { TextDocument *document = TextDocument::constructTextDocument( untitledName(Document::dt_text), p_ktechlab ); handleNewDocument(document); return document; } CircuitDocument *DocManager::createCircuitDocument() { CircuitDocument *document = new CircuitDocument( untitledName(Document::dt_circuit), p_ktechlab ); handleNewDocument(document); if ( KTLConfig::raiseItemSelectors() ) p_ktechlab->showToolView( p_ktechlab->toolView( ComponentSelector::toolViewIdentifier() ) ); return document; } FlowCodeDocument *DocManager::createFlowCodeDocument() { FlowCodeDocument *document = new FlowCodeDocument( untitledName(Document::dt_flowcode), p_ktechlab ); handleNewDocument(document); if ( KTLConfig::raiseItemSelectors() ) p_ktechlab->showToolView( p_ktechlab->toolView( FlowPartSelector::toolViewIdentifier() ) ); return document; } MechanicsDocument *DocManager::createMechanicsDocument() { MechanicsDocument *document = new MechanicsDocument( untitledName(Document::dt_mechanics), p_ktechlab ); handleNewDocument(document); if ( KTLConfig::raiseItemSelectors() ) p_ktechlab->showToolView( p_ktechlab->toolView( MechanicsSelector::toolViewIdentifier() ) ); return document; } CircuitDocument *DocManager::openCircuitFile( const KURL &url, ViewArea *viewArea ) { CircuitDocument *document = new CircuitDocument( url.fileName().remove(url.directory()), p_ktechlab ); if ( !document->openURL(url) ) { KMessageBox::sorry( 0l, i18n("Could not open Circuit file \"%1\"").arg(url.prettyURL()) ); document->deleteLater(); return 0l; } handleNewDocument( document, viewArea ); emit fileOpened(url); return document; } FlowCodeDocument *DocManager::openFlowCodeFile( const KURL &url, ViewArea *viewArea ) { FlowCodeDocument *document = new FlowCodeDocument( url.fileName().remove(url.directory()), p_ktechlab ); if ( !document->openURL(url) ) { KMessageBox::sorry( 0l, i18n("Could not open FlowCode file \"%1\"").arg(url.prettyURL()) ); document->deleteLater(); return 0l; } handleNewDocument( document, viewArea ); emit fileOpened(url); return document; } MechanicsDocument *DocManager::openMechanicsFile( const KURL &url, ViewArea *viewArea ) { MechanicsDocument *document = new MechanicsDocument( url.fileName().remove(url.directory()), p_ktechlab ); if ( !document->openURL(url) ) { KMessageBox::sorry( 0l, i18n("Could not open Mechanics file \"%1\"").arg(url.prettyURL()) ); document->deleteLater(); return 0l; } handleNewDocument( document, viewArea ); emit fileOpened(url); return document; } TextDocument *DocManager::openTextFile( const KURL &url, ViewArea *viewArea ) { TextDocument *document = TextDocument::constructTextDocument( url.fileName().remove(url.directory()), p_ktechlab ); if (!document) return 0l; if ( !document->openURL(url) ) { KMessageBox::sorry( 0l, i18n("Could not open text file \"%1\"").arg(url.prettyURL()) ); document->deleteLater(); return 0l; } handleNewDocument( document, viewArea ); emit fileOpened(url); return document; } #include "docmanager.moc"