docmanager.cpp

00001 /***************************************************************************
00002  *   Copyright (C) 2005 by David Saxton                                    *
00003  *   david@bluehaze.org                                                    *
00004  *                                                                         *
00005  *   This program is free software; you can redistribute it and/or modify  *
00006  *   it under the terms of the GNU General Public License as published by  *
00007  *   the Free Software Foundation; either version 2 of the License, or     *
00008  *   (at your option) any later version.                                   *
00009  ***************************************************************************/
00010 
00011 #include "circuitdocument.h"
00012 #include "docmanager.h"
00013 #include "docmanageriface.h"
00014 #include "flowcodedocument.h"
00015 #include "iteminterface.h"
00016 #include "itemselector.h"
00017 #include "ktechlab.h"
00018 #include "core/ktlconfig.h"
00019 #include "mechanicsdocument.h"
00020 #include "textdocument.h"
00021 #include "textview.h"
00022 #include "viewcontainer.h"
00023 
00024 #include <klocale.h>
00025 #include <kmessagebox.h>
00026 #include <ktabwidget.h>
00027 #include <qfile.h>
00028 
00029 #include <cassert>
00030 
00031 DocManager * DocManager::m_pSelf = 0;
00032 
00033 DocManager * DocManager::self( KTechlab * ktechlab )
00034 {
00035         if ( !m_pSelf )
00036         {
00037                 assert(ktechlab);
00038                 m_pSelf = new DocManager(ktechlab);
00039         }
00040         return m_pSelf;
00041 }
00042 
00043 
00044 DocManager::DocManager( KTechlab * ktechlab )
00045         : QObject( ktechlab ),
00046         p_ktechlab(ktechlab)
00047 {
00048         p_focusedView = 0;
00049         m_countCircuit = 0;
00050         m_countFlowCode = 0;
00051         m_countMechanics = 0;
00052         m_countOther = 0;
00053         p_connectedDocument = 0;
00054         m_nextDocumentID = 1;
00055         m_pIface = new DocManagerIface(this);
00056 }
00057 
00058 
00059 DocManager::~DocManager()
00060 {
00061 }
00062 
00063 
00064 bool DocManager::closeAll()
00065 {
00066         const DocumentList::iterator end = m_documentList.end();
00067         while ( !m_documentList.isEmpty() )
00068         {
00069                 Document *document = m_documentList.first();
00070                 if ( document->fileClose() )
00071                 {
00072                         m_documentList.remove(document);
00073                         removeDocumentAssociations(document);
00074                 }
00075                 else
00076                         return false;
00077         }
00078         return true;
00079 }
00080 
00081 
00082 void DocManager::gotoTextLine( const KURL &url, int line )
00083 {
00084         TextDocument * doc = dynamic_cast<TextDocument*>( openURL(url) );
00085         if (!doc)
00086                 return;
00087         
00088         doc->textView()->gotoLine(line);
00089 }
00090 
00091 
00092 Document* DocManager::openURL( const KURL &url, ViewArea *viewArea )
00093 {
00094         if ( url.isEmpty() )
00095                 return 0;
00096         
00097         if ( url.isLocalFile() )
00098         {
00099                 QFile file(url.path());
00100                 if ( file.open(IO_ReadOnly) == false )
00101                 {
00102                         KMessageBox::sorry( 0, i18n("Could not open '%1'").arg( url.prettyURL() ) );
00103                         return 0;
00104                 }
00105                 file.close();
00106         }
00107         
00108         // If the document is already open, and a specific view area hasn't been
00109         // specified, then just return that document - otherwise, create a new
00110         // view in the viewarea
00111         Document *document = findDocument(url);
00112         if ( document )
00113         {
00114                 if ( viewArea )
00115                         createNewView( document, viewArea );
00116                 else
00117                         giveDocumentFocus( document, viewArea );
00118                 return document;
00119         }
00120         
00121         QString fileName = url.fileName();
00122         QString extension = fileName.right( fileName.length() - fileName.findRev('.') );
00123         
00124         if ( extension == ".circuit" )
00125                 return openCircuitFile( url, viewArea );
00126         
00127         else if ( extension == ".flowcode" )
00128                 return openFlowCodeFile( url, viewArea );
00129         
00130         else if ( extension == ".mechanics" )
00131                 return openMechanicsFile( url, viewArea );
00132         
00133         else
00134                 return openTextFile( url, viewArea );
00135 }
00136 
00137 
00138 Document *DocManager::getFocusedDocument() const
00139 {
00140         Document * doc = p_focusedView ? p_focusedView->document() : 0;
00141         return (doc && !doc->isDeleted()) ? doc : 0;
00142 }
00143 
00144 
00145 void DocManager::giveDocumentFocus( Document * toFocus, ViewArea * viewAreaForNew )
00146 {
00147         if ( !toFocus )
00148                 return;
00149         
00150         if ( View * activeView = toFocus->activeView() )
00151         {
00152                 p_ktechlab->tabWidget()->showPage( activeView->viewContainer() );
00153                 activeView->setFocused();
00154                 activeView->viewContainer()->setFocused();
00155         }
00156         else if ( viewAreaForNew )
00157                 createNewView( toFocus, viewAreaForNew );
00158 }
00159 
00160 
00161 QString DocManager::untitledName( int type )
00162 {
00163         QString name;
00164         switch(type)
00165         {
00166                 case Document::dt_circuit:
00167                 {
00168                         if ( m_countCircuit>1 )
00169                                 name = i18n("Untitled (Circuit %1)").arg(QString::number(m_countCircuit));
00170                         else
00171                                 name = i18n("Untitled (Circuit)");
00172                         m_countCircuit++;
00173                         break;
00174                 }
00175                 case Document::dt_flowcode:
00176                 {
00177                         if ( m_countFlowCode>1 )
00178                                 name = i18n("Untitled (FlowCode %1)").arg(QString::number(m_countFlowCode));
00179                         else
00180                                 name = i18n("Untitled (FlowCode)");
00181                         m_countFlowCode++;
00182                         break;
00183                 }
00184                 case Document::dt_mechanics:
00185                 {
00186                         if ( m_countMechanics>1 )
00187                                 name = i18n("Untitled (Mechanics %1)").arg(QString::number(m_countMechanics));
00188                         else
00189                                 name = i18n("Untitled (Mechanics)");
00190                         m_countMechanics++;
00191                         break;
00192                 }
00193                 default:
00194                 {
00195                         if ( m_countOther>1 )
00196                                 name = i18n("Untitled (%1)").arg(QString::number(m_countOther));
00197                         else
00198                                 name = i18n("Untitled");
00199                         m_countOther++;
00200                         break;
00201                 }
00202         }
00203         return name;
00204 }
00205 
00206 
00207 Document *DocManager::findDocument( const KURL &url ) const
00208 {
00209         // First, look in the associated documents
00210         if ( m_associatedDocuments.contains(url) )
00211                 return m_associatedDocuments[url];
00212         
00213         // Not found, so look in the known documents
00214         const DocumentList::const_iterator end = m_documentList.end();
00215         for ( DocumentList::const_iterator it = m_documentList.begin(); it != end; ++it )
00216         {
00217                 if ( (*it)->url() == url )
00218                         return *it;
00219         }
00220         
00221         return 0;
00222 }
00223 
00224 
00225 void DocManager::associateDocument( const KURL &url, Document *document )
00226 {
00227         if (!document)
00228                 return;
00229         
00230         m_associatedDocuments[url] = document;
00231 }
00232 
00233 
00234 void DocManager::removeDocumentAssociations( Document *document )
00235 {
00236         bool doneErase;
00237         do
00238         {
00239                 doneErase = false;
00240                 const URLDocumentMap::iterator end = m_associatedDocuments.end();
00241                 for ( URLDocumentMap::iterator it = m_associatedDocuments.begin(); it != end; ++it )
00242                 {
00243                         if ( it.data() == document )
00244                         {
00245                                 doneErase = true;
00246                                 m_associatedDocuments.erase(it);
00247                                 break;
00248                         }
00249                 }
00250         }
00251         while (doneErase);
00252 }
00253 
00254 
00255 void DocManager::handleNewDocument( Document *document, ViewArea *viewArea )
00256 {
00257         if ( !document || m_documentList.contains(document) )
00258                 return;
00259         
00260         m_documentList.append(document);
00261         document->setDCOPID(m_nextDocumentID++);
00262         
00263         connect( document, SIGNAL(modifiedStateChanged()), p_ktechlab, SLOT(slotDocModifiedChanged()) );
00264         connect( document, SIGNAL(fileNameChanged(const KURL&)), p_ktechlab, SLOT(slotDocModifiedChanged()) );
00265         connect( document, SIGNAL(fileNameChanged(const KURL&)), p_ktechlab, SLOT(addRecentFile(const KURL&)) );
00266         connect( document, SIGNAL(destroyed(QObject* )), this, SLOT(documentDestroyed(QObject* )) );
00267         connect( document, SIGNAL(viewFocused(View* )), this, SLOT(slotViewFocused(View* )) );
00268         connect( document, SIGNAL(viewUnfocused()), this, SLOT(slotViewUnfocused()) );
00269         
00270         createNewView( document, viewArea );
00271 }
00272 
00273 
00274 View *DocManager::createNewView( Document *document, ViewArea *viewArea )
00275 {
00276         if (!document)
00277                 return 0;
00278         
00279         View *view = 0;
00280         
00281         if (viewArea)
00282                 view = document->createView( viewArea->viewContainer(), viewArea->id() );
00283         
00284         else
00285         {
00286                 ViewContainer *viewContainer = new ViewContainer( document->caption(), p_ktechlab );
00287                 view = document->createView( viewContainer, 0 );
00288                 p_ktechlab->addWindow(viewContainer);
00289         }
00290         
00291         view->setFocused();
00292         return view;
00293 }
00294 
00295 
00296 void DocManager::documentDestroyed( QObject *obj )
00297 {
00298         Document *doc = static_cast<Document*>(obj);
00299         m_documentList.remove(doc);
00300         removeDocumentAssociations(doc);
00301         disableContextActions();
00302 }
00303 
00304 
00305 void DocManager::slotViewFocused( View *view )
00306 {
00307         ViewContainer * vc = static_cast<ViewContainer*>(p_ktechlab->tabWidget()->currentPage());
00308         if (!vc)
00309                 view = 0;
00310         
00311         if (!view)
00312                 return;
00313         
00314         // This function can get called with a view that is not in the current view
00315         // container (such as when the user right clicks and then the popup is
00316         // destroyed - not too sure why, but this is the easiest way to fix it).
00317         if ( view->viewContainer() != vc )
00318                 view = vc->activeView();
00319         
00320         if ( !view || (View*)p_focusedView == view )
00321                 return;
00322         
00323         if (p_focusedView)
00324                 slotViewUnfocused();
00325         
00326         p_focusedView = view;
00327         
00328         if ( TextView * textView = dynamic_cast<TextView*>((View*)p_focusedView) )
00329                 p_ktechlab->factory()->addClient( textView->kateView() );
00330         else
00331                 p_ktechlab->factory()->addClient( p_focusedView );
00332         
00333         Document *document = view->document();
00334         
00335         connect( document, SIGNAL(undoRedoStateChanged()), p_ktechlab, SLOT(slotDocUndoRedoChanged()) );
00336         p_connectedDocument = document;
00337                 
00338         if ( document->type() == Document::dt_circuit ||
00339                            document->type() == Document::dt_flowcode ||
00340                            document->type() == Document::dt_mechanics )
00341         {
00342                 ItemDocument *cvb = static_cast<ItemDocument*>(view->document());
00343                 ItemInterface::self()->slotItemDocumentChanged(cvb);
00344         }
00345         
00346         p_ktechlab->slotDocUndoRedoChanged();
00347         p_ktechlab->slotDocModifiedChanged();
00348         p_ktechlab->requestUpdateCaptions();
00349 }
00350 
00351 
00352 void DocManager::slotViewUnfocused()
00353 {
00354         p_ktechlab->removeGUIClients();
00355         disableContextActions();
00356         
00357         if (!p_focusedView)
00358                 return;
00359         
00360         if (p_connectedDocument)
00361         {
00362                 disconnect( p_connectedDocument, SIGNAL(undoRedoStateChanged()), p_ktechlab, SLOT(slotDocUndoRedoChanged()) );
00363                 p_connectedDocument = 0;
00364         }
00365         
00366         ItemInterface::self()->slotItemDocumentChanged(0);
00367         p_focusedView = 0;
00368         
00369 //      p_ktechlab->setCaption( 0 );
00370         p_ktechlab->requestUpdateCaptions();
00371 }
00372 
00373 
00374 void DocManager::disableContextActions()
00375 {
00376         p_ktechlab->action("file_save")->setEnabled(false);
00377         p_ktechlab->action("file_save_as")->setEnabled(false);
00378         p_ktechlab->action("file_close")->setEnabled(false);
00379         p_ktechlab->action("file_print")->setEnabled(false);
00380         p_ktechlab->action("edit_undo")->setEnabled(false);
00381         p_ktechlab->action("edit_redo")->setEnabled(false);
00382         p_ktechlab->action("edit_cut")->setEnabled(false);
00383         p_ktechlab->action("edit_copy")->setEnabled(false);
00384         p_ktechlab->action("edit_paste")->setEnabled(false);
00385         p_ktechlab->action("view_split_leftright")->setEnabled(false);
00386         p_ktechlab->action("view_split_topbottom")->setEnabled(false);
00387 }
00388 
00389 
00390 TextDocument *DocManager::createTextDocument()
00391 {
00392         TextDocument *document = TextDocument::constructTextDocument( untitledName(Document::dt_text), p_ktechlab );
00393         handleNewDocument(document);
00394         return document;
00395 }
00396 
00397 
00398 CircuitDocument *DocManager::createCircuitDocument()
00399 {
00400         CircuitDocument *document = new CircuitDocument( untitledName(Document::dt_circuit), p_ktechlab );
00401         handleNewDocument(document);
00402         if ( KTLConfig::raiseItemSelectors() )
00403                 p_ktechlab->showToolView( p_ktechlab->toolView( ComponentSelector::toolViewIdentifier() ) );
00404         return document;
00405 }
00406 
00407 
00408 FlowCodeDocument *DocManager::createFlowCodeDocument()
00409 {
00410         FlowCodeDocument *document = new FlowCodeDocument( untitledName(Document::dt_flowcode), p_ktechlab );
00411         handleNewDocument(document);
00412         if ( KTLConfig::raiseItemSelectors() )
00413                 p_ktechlab->showToolView( p_ktechlab->toolView( FlowPartSelector::toolViewIdentifier() ) );
00414         return document;
00415 }
00416 
00417 
00418 MechanicsDocument *DocManager::createMechanicsDocument()
00419 {
00420         MechanicsDocument *document = new MechanicsDocument( untitledName(Document::dt_mechanics), p_ktechlab );
00421         handleNewDocument(document);
00422         if ( KTLConfig::raiseItemSelectors() )
00423                 p_ktechlab->showToolView( p_ktechlab->toolView( MechanicsSelector::toolViewIdentifier() ) );
00424         return document;
00425 }
00426 
00427 
00428 CircuitDocument *DocManager::openCircuitFile( const KURL &url, ViewArea *viewArea )
00429 {
00430         CircuitDocument *document = new CircuitDocument( url.fileName().remove(url.directory()), p_ktechlab );
00431         
00432         if ( !document->openURL(url) )
00433         {
00434                 KMessageBox::sorry( 0, i18n("Could not open Circuit file \"%1\"").arg(url.prettyURL()) );
00435                 document->deleteLater();
00436                 return 0;
00437         }
00438         
00439         handleNewDocument( document, viewArea );
00440         emit fileOpened(url);
00441         return document;
00442 }
00443 
00444 
00445 FlowCodeDocument *DocManager::openFlowCodeFile( const KURL &url, ViewArea *viewArea )
00446 {
00447         FlowCodeDocument *document = new FlowCodeDocument( url.fileName().remove(url.directory()), p_ktechlab );
00448         
00449         if ( !document->openURL(url) )
00450         {
00451                 KMessageBox::sorry( 0, i18n("Could not open FlowCode file \"%1\"").arg(url.prettyURL()) );
00452                 document->deleteLater();
00453                 return 0;
00454         }
00455         
00456         handleNewDocument( document, viewArea );
00457         emit fileOpened(url);
00458         return document;
00459 }
00460 
00461 
00462 MechanicsDocument *DocManager::openMechanicsFile( const KURL &url, ViewArea *viewArea )
00463 {
00464         MechanicsDocument *document = new MechanicsDocument( url.fileName().remove(url.directory()), p_ktechlab );
00465         
00466         if ( !document->openURL(url) )
00467         {
00468                 KMessageBox::sorry( 0, i18n("Could not open Mechanics file \"%1\"").arg(url.prettyURL()) );
00469                 document->deleteLater();
00470                 return 0;
00471         }
00472         
00473         handleNewDocument( document, viewArea );
00474         emit fileOpened(url);
00475         return document;
00476         
00477 }
00478 
00479 
00480 TextDocument *DocManager::openTextFile( const KURL &url, ViewArea *viewArea )
00481 {
00482         TextDocument *document = TextDocument::constructTextDocument( url.fileName().remove(url.directory()), p_ktechlab );
00483         
00484         if (!document)
00485                 return 0;
00486         
00487         if ( !document->openURL(url) )
00488         {
00489                 KMessageBox::sorry( 0, i18n("Could not open text file \"%1\"").arg(url.prettyURL()) );
00490                 document->deleteLater();
00491                 return 0;
00492         }
00493         
00494         handleNewDocument( document, viewArea );
00495         emit fileOpened(url);
00496         return document;
00497 }
00498 
00499 
00500 #include "docmanager.moc"

Generated on Tue May 8 17:05:29 2007 for KTechLab by  doxygen 1.5.1