Don't keep compiling/run if something failed.
[kdevelopdvcssupport.git] / plugins / teamwork / documentwrapper.cpp
blob930ed1aee1b6148c927a88debb2c262aa4d72d26
1 /***************************************************************************
2 Copyright 2006 David Nolden <david.nolden.kdevelop@art-master.de>
3 ***************************************************************************/
5 /***************************************************************************
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 ***************************************************************************/
14 #include "documentwrapper.h"
15 #include "kdevteamwork_messages.h"
16 #include "kdevteamworkplugin.h"
17 #include <QStandardItemModel>
18 #include <QModelIndex>
19 #include <QMenu>
20 #include <QVariant>
21 #include <QFileInfo>
22 #include <QFile>
23 #include <kmessagebox.h>
24 #include <klocalizedstring.h>
25 #include <k3process.h>
26 #include <ktexteditor/document.h>
27 #include <ktexteditor/range.h>
28 #include <interfaces/idocumentcontroller.h>
29 #include <interfaces/idocument.h>
30 #include "lib/dynamictext/dynamictext.h"
31 #include "kdevteamwork_helpers.h"
32 #include "collaborationmanager.h"
33 #include "filecollaborationmessages.h"
34 #include "lib/network/basicsession.h"
35 #include "utils.h"
36 #include "lib/dynamictext/verify.h"
37 #include "filesynchronizemessage.h"
38 #include "qdynamictext.h"
39 #include "vectortimestampeditor.h"
40 #include "kdevteamwork.h"
41 #include "patchesmanager.h"
42 #include "teamworkfoldermanager.h"
43 #include "filecollaborationsession.h"
44 #include "patchmessage.h"
45 #include "filecollaborationmanager.h"
46 #include "lib/network/messagetypeset.h"
47 #include "lib/network/messagesendhelper.h"
48 #include <interfaces/iuicontroller.h> /* defines [function] activeMainWindow */
49 #include <interfaces/icore.h> /* defines [function] uiController */
51 /* Exclude this file from doublequote_chars check as krazy doesn't understand
52 std::string*/
53 //krazy:excludeall=doublequote_chars
55 using namespace KDevelop;
57 #define IFDEBUG( x ) /**/
58 //#define IFDEBUG( x ) x
60 struct DocumentWrapperTreeAction : public StandardCollaborationTreeAction<DocumentWrapper> {
61 DocumentWrapperTreeAction( DocumentWrapper* w ) : StandardCollaborationTreeAction<DocumentWrapper>( w ) {}
62 virtual void doubleClicked() {
63 if ( target ) {
64 target->openDocument( true );
67 virtual void clicked() {}
68 virtual void fillContextMenu( QMenu* menu ) {
69 if ( target )
70 target->fillContextMenu( 0, menu );
75 bool DocumentWrapper::hadError() const {
76 return m_hadError;
79 uint DocumentWrapper::id() const {
80 return m_id;
83 DocumentWrapper::DocumentWrapper( uint id, const LoggerPointer& logger, QString fileName, uint ownIndex, bool readFile_, FileCollaborationSession* session, bool fromBuffer ) :
84 SafeLogger( logger, ~( "document-wrapper \"" + fileName + "\": " ) ),
85 m_text( new QDynamicText() ),
86 m_block( false ),
87 m_realFile( readFile_ ),
88 m_fileName( fileName ),
89 m_document( 0 ),
90 m_session( session ),
91 m_ownIndex( ownIndex ),
92 m_id( id ),
93 m_hadError( false ),
94 m_disabled( false ),
95 m_dead( false ),
96 m_dispatcher( *this ){
97 //openDocument();
98 out( Logger::Debug ) << "DocumentWrapper for" << fileName << "created:" << ownIndex << "" << readFile_;
99 if ( m_realFile )
100 readFile( fromBuffer );
102 connect( m_text.data(), SIGNAL( stateChanged( QDynamicText& ) ), this, SLOT( stateChanged() ) );
105 QIcon DocumentWrapper::icon() const {
106 if ( m_dead )
107 return IconCache::getIconStatic( "collaboration_file_dead" );
108 if ( !m_disabled )
109 return IconCache::getIconStatic( "collaboration_file" );
110 else
111 return IconCache::getIconStatic( "collaboration_file_disabled" );
114 void DocumentWrapper::updateTree( QModelIndex& i, QStandardItemModel* model ) {
115 model->setData( i, fileName(), Qt::DisplayRole );
116 model->setData( i, icon(), Qt::DecorationRole );
117 QVariant v;
118 v.setValue<CollaborationTreeActionPointer>( new DocumentWrapperTreeAction( this ) );
119 model->setData( i, v, Qt::UserRole );
122 void DocumentWrapper::fillContextMenu( int /*var*/, QMenu* menu ) {
123 QMenu * m = new QMenu( menu );
124 m->setTitle( "Save Visible State" );
125 m->addAction( "As Patch", this, SLOT( saveAsPatch() ) );
126 //m->addAction( "To New Buffer", this, SLOT( saveNewBuffer() ) );
127 //m->addSeparator();
128 m->addAction( QString( "As %1" ).arg( m_fileName ), this, SLOT( saveAsBufferFile() ) );
129 menu->addMenu( m );
132 if ( m_disabled )
133 menu->addAction( "Enable Editing", this, SLOT( toggleEnabled() ) );
134 else if ( m_session->isMasterSession() )
135 menu->addAction( "Disable Editing", this, SLOT( toggleEnabled() ) );
137 if ( m_session->isMasterSession() || m_dead ) {
138 menu->addSeparator();
139 menu->addAction( "Remove", this, SLOT( remove
140 () ) );
143 menu->addSeparator();
144 menu->addAction( "Manage Dynamic Text", this, SLOT( manageDynamicText() ) );
147 QString DocumentWrapper::text() const {
148 return ~m_text->text().text();
151 VectorTimestamp DocumentWrapper::state() const {
152 return m_text->state();
155 const QDynamicText& DocumentWrapper::dynamicText() const {
156 return * m_text;
159 bool DocumentWrapper::checkDocumentSync() const {
160 if ( m_document && m_document->textDocument() ) {
161 return m_document->textDocument() ->text() == ~m_text->text().text();
162 } else {
163 return true;
167 void DocumentWrapper::remove
168 () {}
171 void DocumentWrapper::toggleEnabled() {
172 m_disabled = !m_disabled;
173 out( Logger::Debug ) << "Editing is now" << ( m_disabled ? "disabled" : "enabled");
176 void DocumentWrapper::saveAsBufferFile() {
177 KUrl u = TeamworkFolderManager::workspaceAbsolute( m_fileName );
179 IDocument* doc = KDevTeamworkPlugin::staticDocumentController() ->openDocument( u, KTextEditor::Cursor() );
181 if ( doc && doc->textDocument() ) {
182 if ( doc->state() == IDocument::Modified || doc->state() == IDocument::DirtyAndModified ) {
183 int answer = KMessageBox::warningYesNo( KDevTeamworkPlugin::staticCore()->uiController()->activeMainWindow()->window(), i18n( "The buffer of %1 is modified, should the content be replaced?" , m_fileName ) );
184 if ( answer != KMessageBox::Yes )
185 return ;
187 doc->textDocument() ->setText( ~m_text->text().text() );
189 } else {
190 err() << "saveAsBufferFile(): could not open document for" << u.toLocalFile();
194 OutputFileWriter::OutputFileWriter( const QString& file ) : m_file( file ), m_failed( false ) {
195 if ( !m_file.open( QIODevice::WriteOnly ) )
196 throw QString( "could not open file %1" ).arg( file );
199 bool OutputFileWriter::failed() const {
200 return m_failed;
203 void OutputFileWriter::receivedStdout( K3Process */*proc*/, char *buffer, int buflen ) {
204 if ( m_file.write( buffer, buflen ) != buflen ) {
205 m_failed = true;
209 LocalPatchSourcePointer DocumentWrapper::saveAsPatch( bool addToList, bool edit ) {
210 try {
211 KDevTeamwork * tw = KDevTeamwork::self();
213 PatchesManager* pm = tw->patchesManager();
215 QString peer = m_session->firstPeerName();
216 if ( m_session->isMasterSession() )
217 peer = "local";
219 LocalPatchSourcePointer::Locked l = new LocalPatchSource();
220 l->name = ~( m_session->name() + "@" + peer + "_" + QDateTime::currentDateTime().toString( Qt::ISODate ) );
221 l->type = "text/x-diff";
222 l->applyCommand = "-p0";
223 l->unApplyCommand = "-p0 -R";
224 l->userIdentity = m_session->manager() ->teamwork() ->currentUserIdentity();
226 KUrl u = TeamworkFolderManager::createUniqueFile( "patches", "diff", ~l->name, "collab_", "" );
228 l->filename = ~TeamworkFolderManager::teamworkRelative( u, "patches" );
230 KUrl workingDir = TeamworkFolderManager::createUniqueDirectory( "temp", m_session->name(), "diff_" );
231 KUrl subFolder( TeamworkFolderManager::teamworkRelative( workingDir ) );
232 subFolder.addPath( QFileInfo( m_fileName ).path() );
234 KUrl tempCurrent = TeamworkFolderManager::createUniqueFile( subFolder.toLocalFile(), m_fileName );
235 KUrl tempBase = TeamworkFolderManager::createUniqueFile( subFolder.toLocalFile(), m_fileName, "base_" );
237 TeamworkFolderManager::self() ->registerTempItem( tempCurrent );
238 TeamworkFolderManager::self() ->registerTempItem( tempBase );
241 QByteArray path = tempCurrent.toLocalFile().toUtf8();
242 std::ofstream fCurrent( path.data(), ios_base::out );
243 if ( !fCurrent.is_open() )
244 throw "could not open file for writing: " + tempCurrent.toLocalFile();
245 fCurrent << m_text->text().text();
248 QByteArray path = tempBase.toLocalFile().toUtf8();
249 std::ofstream fBase( path.data(), ios_base::out );
250 if ( !fBase.is_open() )
251 throw "could not open file for writing: " + tempBase.toLocalFile();
252 fBase << m_text->initialText();
254 K3Process proc;
255 ///@todo make this work with remote files
256 OutputFileWriter ow( u.toLocalFile() );
257 proc.setWorkingDirectory( workingDir.toLocalFile() );
258 QString cmdLine = + + " " + tempCurrent.toLocalFile() + " > " + u.toLocalFile();
259 proc.setPriority( K3Process::PrioLowest );
260 proc << "diff";
261 proc << "--unified=4";
262 proc << tempBase.toLocalFile();
263 proc << tempCurrent.toLocalFile();
265 connect( &proc, SIGNAL( receivedStdout ( K3Process *, char *, int ) ), &ow, SLOT( receivedStdout( K3Process*, char*, int ) ) );
267 if ( ow.failed() )
268 throw QString( "writing to %1 failed" ).arg( u.prettyUrl() );
270 out( Logger::Debug ) << "saveAsPatch(..) executing \"diff --unified=4 " + tempBase.toLocalFile() + " " + tempCurrent.toLocalFile() + "\"";
272 proc.start( K3Process::Block, K3Process::Stdout );
273 if ( addToList )
274 pm->addPatch( l );
275 if ( edit )
276 pm->showPatchInfo( l, true );
278 return l;
279 } catch ( const QString & str ) {
280 err() << "saveAsPatch():" << str;
281 } catch ( const char * str ) {
282 err() << "saveAsPatch():" << str;
284 return 0;
287 void DocumentWrapper::saveNewBuffer() {
288 ///It would be nice to create a nameless buffer here and insert the text
291 void DocumentWrapper::manageDynamicText() {
292 new VectorTimestampEditor( logger(), this, false, m_text, true );
295 void DocumentWrapper::stateChanged() {
296 if ( m_block )
297 return ;
298 fillDocumentText();
301 bool DocumentWrapper::synchronize( const UserPointer& user ) {
302 if ( m_dead )
303 return false;
305 out( Logger::Debug ) << "synchronizing with" << user.unsafe()->safeName();
307 UserPointer::Locked l = user;
308 if ( l && l->online().session() ) {
309 return globalMessageSendHelper().send<FileSynchronize>( l->online().session().unsafe(), fileName(), *m_text, true, id(), m_session->id() );
310 } else {
311 err() << "cannot send synchronization-message because the user cannot be locked, or is not online";
312 return false;
316 int DocumentWrapper::receiveMessage( FileEditRejectMessage* msg ) {
317 if ( m_session->isMasterSession() ) {
318 out( Logger::Warning ) << "got a reject-message from a client, sending complete synchronization";
319 synchronize( msg->info().user() );
320 return 0;
323 ///A reject-message contains a new state that should be applied
324 VectorTimestamp v = msg->timeStamp();
325 try {
326 m_text->changeState( v );
327 m_text->cut();
328 } catch ( const DynamicTextError & err ) {
329 ///There is no other way than resynchronizing the whole file
330 out() << "error while handling a reject, resynchronizing. Error:" << err.what();
331 globalMessageSendHelper().sendReply<FileEditRejectMessage>( msg, VectorTimestamp(), id(), m_session->id() );
333 return 1;
336 int DocumentWrapper::receiveMessage( MessageInterface* msg ) {
337 out( Logger::Warning ) << "got unknown message of type" << msg->name();
338 return 0;
341 int DocumentWrapper::receiveMessage( FileEditMessage* msg ) {
342 try {
343 if ( ( m_disabled || m_dead ) && m_session->isMasterSession() ) {
344 globalMessageSendHelper().sendReply<FileEditRejectMessage>( msg, m_text->tailState(), id(), m_session->id() );
345 return 0;
347 FileEditMessage * emsg = dynamic_cast<FileEditMessage*>( msg );
349 Block b( m_block );
350 bool wasTail = m_text->state() == m_text->tailState();
351 m_text->insert( emsg->timeStamp(), emsg->replacement() );
353 if ( wasTail ) {
354 m_text->text().registerNotifier( this );
355 m_text->changeState();
356 m_text->text().unregisterNotifier();
360 } catch ( const DynamicTextError & error ) {
361 ///@todo error-handling
362 err() << "receiveMessage( FileEditMessage" << msg->timeStamp() << "" << msg->replacement() << "):" << error.what();
363 globalMessageSendHelper().sendReply<FileEditRejectMessage>( msg, m_text->tailState(), id(), m_session->id() );
364 m_text->text().unregisterNotifier(); //@todo use a little wrapper-class for this
366 return 1;
369 void DocumentWrapper::notifyFlexibleTextErase( int position, int length ) {
370 if ( m_document && m_document->textDocument() ) {
371 Block b( m_block );
372 int line, column;
374 m_text->text().linearToLineColumn( position, line, column );
375 if ( line == -1 || column == -1 )
376 throw DynamicTextError( "receiveMessage( FileEditMessage ): could not convert index to cursor" );
378 KTextEditor::Cursor start( line, column );
381 m_text->text().linearToLineColumn( position + length, line, column );
383 if ( line == -1 || column == -1 )
384 throw DynamicTextError( "receiveMessage( FileEditMessage ): could not convert index to cursor" );
386 KTextEditor::Cursor end( line, column );
389 m_document->textDocument() ->replaceText( KTextEditor::Range( start, end ), "" );
393 void DocumentWrapper::notifyFlexibleTextInsert( int position, const std::string& text ) {
394 if ( m_document && m_document->textDocument() ) {
395 Block b( m_block );
396 int line, column;
398 m_text->text().linearToLineColumn( position, line, column );
399 if ( line == -1 || column == -1 )
400 throw DynamicTextError( "receiveMessage( FileEditMessage ): could not convert index to cursor" );
402 KTextEditor::Cursor start( line, column );
404 m_document->textDocument() ->replaceText( KTextEditor::Range( start, start ), toQ( text.c_str() ) );
408 void DocumentWrapper::notifyFlexibleTextReplace( int position, int length, const std::string& replacement ) {
409 if ( m_document && m_document->textDocument() ) {
410 Block b( m_block );
411 int line, column;
413 m_text->text().linearToLineColumn( position, line, column );
414 if ( line == -1 || column == -1 )
415 throw DynamicTextError( "receiveMessage( FileEditMessage ): could not convert index to cursor" );
417 KTextEditor::Cursor start( line, column );
420 m_text->text().linearToLineColumn( position + length, line, column );
422 if ( line == -1 || column == -1 )
423 throw DynamicTextError( "receiveMessage( FileEditMessage ): could not convert index to cursor" );
425 KTextEditor::Cursor end( line, column );
428 m_document->textDocument() ->replaceText( KTextEditor::Range( start, end ), toQ( replacement.c_str() ) );
432 void DocumentWrapper::processMessage( DocumentWrapperMessage* msg ) {
434 /*if ( !checkDocumentSync() ) {
435 if ( m_document && m_document->textDocument() ) {
436 out( Logger::Warning ) << "processMessage(begin): document and dynamictext got out of sync! Resynchronizing";
437 fillDocumentText();
441 IFDEBUG( out( Logger::Debug ) << "processMessage(..) processing" << msg->name() );
443 m_dispatcher( msg );
445 if ( !checkDocumentSync() ) {
446 if ( m_document && m_document->textDocument() ) {
447 out( Logger::Warning ) << "processMessage(end): document and dynamictext got out of sync! Resynchronizing";
448 fillDocumentText();
453 void DocumentWrapper::documentDestroyed() {
454 m_document = 0;
457 QString DocumentWrapper::fileName() const {
458 return m_fileName;
461 IDocument* DocumentWrapper::document() {
462 return m_document;
465 void DocumentWrapper::fillDocumentText() {
466 Block b( m_block );
467 if ( m_document && m_document->textDocument() ) {
468 m_document->textDocument() ->setText( ~m_text->text().text() );
469 } else {
470 err() << "cannot update document-text: no document available";
474 void DocumentWrapper::openDocument( bool toForeground ) {
475 try {
476 if ( m_document ) {
477 if( toForeground )
478 KDevTeamworkPlugin::staticDocumentController() ->activateDocument( m_document );
479 return ;
482 out( Logger::Debug ) << "openDocument()" << fileName() << "" << toForeground;
484 if ( m_tempFile.isEmpty() ) {
485 KUrl subfolder( QString( "filecollaboration" ) );
486 subfolder.addPath( m_session->name() + "_" + QString( "%1").arg(m_session->id() ) );
488 QString location;
489 if ( m_session->isMasterSession() ) {
490 location = "local";
491 } else {
492 location = m_session->firstPeerName();
495 ///@todo make this work work remote files
496 m_tempFile = TeamworkFolderManager::createUniqueFile( subfolder.toLocalFile(), m_fileName, "", "@" + m_session->name() ).toLocalFile();
499 out( Logger::Debug ) << "temporary file for" << fileName() << "is" << m_tempFile;
501 m_document = KDevTeamworkPlugin::staticDocumentController() ->openDocument( m_tempFile, KTextEditor::Cursor(), toForeground == true ? KDevelop::IDocumentController::DefaultMode : KDevelop::IDocumentController::DoNotActivate );
503 if ( m_document ) {
504 KTextEditor::Document * doc = m_document->textDocument();
505 if ( !doc ) {
506 m_document = 0;
507 throw "could not open as text-document";
509 fillDocumentText();
511 /*connect( m_document, SIGNAL( destroyed( QObject* ) ), this, SLOT( documentDestroyed() ) );*/
512 connect( m_document->textDocument(), SIGNAL( destroyed( QObject* ) ), this, SLOT( documentDestroyed() ) );
513 connect( doc, SIGNAL( textInserted ( KTextEditor::Document *,
514 const KTextEditor::Range & ) ), this, SLOT( textInserted ( KTextEditor::Document *,
515 const KTextEditor::Range & ) ) );
516 connect( doc, SIGNAL( textRemoved ( KTextEditor::Document *,
517 const KTextEditor::Range & ) ), this, SLOT( textRemoved ( KTextEditor::Document *,
518 const KTextEditor::Range & ) ) );
519 connect( doc, SIGNAL( textChanged ( KTextEditor::Document *,
520 const KTextEditor::Range &,
521 const KTextEditor::Range & ) ), this, SLOT( textChanged ( KTextEditor::Document *,
522 const KTextEditor::Range &,
523 const KTextEditor::Range & ) ) );
524 } else {
525 throw "could not open document";
527 } catch ( const QString & str ) {
528 err() << "openDocument():" << str;
529 } catch ( const char * str ) {
530 err() << "openDocument():" << str;
534 uint getPositionInDocument( KTextEditor::Document * doc, const KTextEditor::Cursor& cursor ) {
535 QString str = doc->text( KTextEditor::Range( KTextEditor::Cursor( 0, 0 ), cursor ) );
536 return str.length();
539 void DocumentWrapper::textChanged ( KTextEditor::Document * document, const KTextEditor::Range & oldRange, const KTextEditor::Range & newRange ) {
540 if ( m_block )
541 return ;
542 out( Logger::Debug ) << "textChanged";
544 VectorTimestamp v( m_text->state() );
545 v.setPrimaryIndex( m_ownIndex );
546 v.increase();
548 int start = m_text->text().lineColumnToLinear( oldRange.start().line(), oldRange.start().column() );
549 int end = m_text->text().lineColumnToLinear( oldRange.end().line(), oldRange.end().column() );
551 if ( start == -1 || end == -1 || start == end ) {
552 err() << "textRemoved(..): DynamicText and Document seem to be out of sync";
554 fillDocumentText();
555 return ;
558 std::string oldText = m_text->text().substr( start, end - start );
559 QString newText = document->text( newRange );
561 if ( oldRange.end().line() == oldRange.start().line() && newRange.end().line() == newRange.start().line() ) {
562 out( Logger::Debug ) << "textChanged at" << start << ":" << oldText << "->" << newText;
563 } else {
564 out( Logger::Debug ) << "textChanged at" << start;
567 ///It might be better to model the edit by one removal and one insertion, because that allows better resolution of conflicts.(Think about if it should be like that)
568 SimpleReplacement r( start, ~newText, oldText );
570 try {
571 DYN_VERIFY( !m_disabled );
572 DYN_VERIFY_SAME( m_text->state(), m_text->tailState() );
573 Block b( m_block );
574 m_text->insert( v, r );
575 } catch ( const DynamicTextError & error ) {
576 err() << "error in textRemoved(..):" << error.what();
577 fillDocumentText();
578 return ;
581 if ( !m_dead )
582 emit publishEdit( v, r, this );
585 ///All the line/column to/from linear conversion is very slow and should be done different
586 void DocumentWrapper::textRemoved ( KTextEditor::Document * /*document*/, const KTextEditor::Range & range ) {
587 if ( m_block )
588 return ;
589 int start = m_text->text().lineColumnToLinear( range.start().line(), range.start().column() );
590 int end = m_text->text().lineColumnToLinear( range.end().line(), range.end().column() );
592 if ( start == -1 || end == -1 ) {
593 err() << "textRemoved(..): DynamicText and Document seem to be out of sync";
594 fillDocumentText();
595 return ;
598 std::string oldText = m_text->text().substr( start, end - start );
600 if ( range.end().line() == range.start().line() ) {
601 IFDEBUG( out( Logger::Debug ) << "textRemoved at" << start << ":" << document->text( range ) );
602 } else {
603 IFDEBUG( out( Logger::Debug ) << "textRemoved at" << start );
606 SimpleReplacement r( start, "", oldText );
608 VectorTimestamp v;
609 try {
610 DYN_VERIFY( !m_disabled );
611 DYN_VERIFY_SAME( m_text->state(), m_text->tailState() );
612 Block b( m_block );
613 v = m_text->insert( m_ownIndex, r );
614 } catch ( const DynamicTextError & error ) {
615 err() << "error in textRemoved(..):" << error.what();
616 fillDocumentText();
617 return ;
620 if ( !m_dead )
621 emit publishEdit( v, r, this );
624 void DocumentWrapper::textInserted ( KTextEditor::Document * document, const KTextEditor::Range & range ) {
625 if ( m_block )
626 return ;
627 VectorTimestamp v;
629 QString newText = document->text( range );
630 uint pos = m_text->text().lineColumnToLinear( range.start().line(), range.start().column() );
632 if ( range.end().line() == range.start().line() ) {
633 IFDEBUG( out( Logger::Debug ) << "textInserted at" << pos << ":" << document->text( range ) );
634 } else {
635 IFDEBUG( out( Logger::Debug ) << "textInserted at" << pos );
638 SimpleReplacement r = SimpleReplacement( pos, ~newText, "" );
640 try {
641 DYN_VERIFY_SAME( m_text->state(), m_text->tailState() );
642 DYN_VERIFY( !m_disabled );
643 Block b( m_block );
644 v = m_text->insert( m_ownIndex, r );
645 } catch ( const DynamicTextError & error ) {
646 err() << "error in textInserted(..):" << error.what();
647 fillDocumentText();
648 return ;
651 if ( !m_dead )
652 emit publishEdit( v, r, this );
655 std::string DocumentWrapper::logPrefix() {
656 return "DocumentWrapper for " + ~fileName() + ": ";
659 int DocumentWrapper::receiveMessage( FileSynchronize* msg ) {
660 ///@todo merge synchronizations from different clients when self was crashed
661 /*if ( !m_text->state().isZero() ) {
662 err() << "got synchronization although timestamp already is" << m_text->state().print();
663 return ;
665 out( Logger::Debug ) << "got synchronization - current Timestamp:" << m_text->state().print() << "new:" << msg->state().print();
667 try {
668 m_text = msg->createDynamicText();
669 connect( m_text.data(), SIGNAL( stateChanged( QDynamicText& ) ), this, SLOT( stateChanged() ) );
670 fillDocumentText();
671 globalMessageSendHelper().sendReply<KDevSystemMessage>( msg, KDevSystemMessage::ActionSuccessful );
672 } catch ( const DynamicTextError & error ) {
673 err() << "error while synchronization:" << error.what();
674 globalMessageSendHelper().sendReply<KDevSystemMessage>( msg, KDevSystemMessage::ActionFailed );
677 return 1;
680 bool DocumentWrapper::dead() const {
681 return m_dead;
684 bool DocumentWrapper::disabled() const {
685 return m_disabled;
688 void DocumentWrapper::setDisabled( bool disabled ) {
689 m_disabled = disabled;
692 void DocumentWrapper::setDead( bool dead ) {
693 m_dead = dead;
696 void DocumentWrapper::readFile( bool fromBuffer ) throw ( QString ) {
697 KUrl u = TeamworkFolderManager::workspaceAbsolute( m_fileName );
699 if ( !m_text->state().isZero() ) {
700 out( Logger::Warning ) << "readFile called although state already is" << m_text->state().print();
703 QString txt;
705 if ( fromBuffer ) {
706 IDocument * doc = KDevTeamworkPlugin::staticDocumentController() ->documentForUrl( u );
707 if ( doc && doc->textDocument() ) {
708 txt = doc->textDocument() ->text();
712 if ( txt.isEmpty() ) {
713 if ( !u.isLocalFile() )
714 throw QString( "file is not local" );
715 if ( !QFileInfo( u.toLocalFile() ).exists() )
716 throw QString( "file does not exist" );
718 QFile f( u.toLocalFile() );
719 if ( !f.open( QIODevice::ReadOnly ) )
720 throw QString( "could not open file" );
722 ///@todo What about encoding etc. ?
723 QByteArray b = f.readAll();
724 Block bl( m_block );
725 m_text = new QDynamicText( VectorTimestamp( m_ownIndex, VectorTimestamp() ), b.data() );
726 } else {
727 m_text = new QDynamicText( VectorTimestamp( m_ownIndex, VectorTimestamp() ), txt.toUtf8().data() );
729 /*m_text->changeState();
730 m_text->insert( m_ownIndex, SimpleReplacement( 0, b.data(), m_text->text() ) );*/
733 #include "documentwrapper.moc"
735 // kate: space-indent on; indent-width 2; tab-width 2; replace-tabs on