Don't keep compiling/run if something failed.
[kdevelopdvcssupport.git] / plugins / teamwork / filecollaborationsession.cpp
blob9c17b26652bbda67de253265e6d2ed27818210af
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 "filecollaborationsession.h"
16 Q_DECLARE_METATYPE( Teamwork::UserPointer )
18 #include <sstream>
19 #include <QAction>
20 #include <QMenu>
21 #include <QTimer>
22 #include <QStandardItemModel>
23 #include <QModelIndex>
25 #include <interfaces/idocumentcontroller.h>
26 #include <interfaces/idocument.h>
28 #include <krandom.h>
29 #include <ktexteditor/document.h>
30 #include <ktexteditor/cursor.h>
32 #include "lib/network/messagesendhelper.h"
33 #include "lib/network/messagetypeset.h"
35 #include "filecollaborationmanager.h"
36 #include "lib/dynamictext/vectortimestamp.h"
37 #include "kdevteamwork_user.h"
38 #include "kdevteamworkplugin.h"
39 #include "documentwrapper.h"
40 #include "patchesmanager.h"
41 #include "kdevteamwork_helpers.h"
44 #include "filesynchronizemessage.h"
45 #include "teamworkfoldermanager.h"
47 /* Exclude this file from doublequote_chars check as krazy doesn't understand
48 std::string*/
49 //krazy:excludeall=doublequote_chars
51 using namespace KDevelop;
53 CROSSMAP_KEY_EXTRACTOR( FileCollaborationPointer, FileCollaborationPointer, 0, value )
54 CROSSMAP_KEY_EXTRACTOR( FileCollaborationPointer, UserPointer, 0, value->user() )
56 CROSSMAP_KEY_EXTRACTOR( DocumentWrapperPointer, QString, 0, value->fileName() )
57 CROSSMAP_KEY_EXTRACTOR( DocumentWrapperPointer, uint, 0, value->id() )
59 FileCollaborationSession::FileCollaborationSession( QString name, CollabFileList files, FileCollaborationManager* manager, uint primaryIndex, CollabSessionId id ) :
60 SafeLogger( manager->teamwork() ->logger(), "in FileCollaborationSession:" ),
61 m_manager( manager ),
62 m_allowSentDocuments( false ),
63 m_isMasterSession( primaryIndex == 0 ),
64 m_primaryIndex( primaryIndex ),
65 m_indexCount( primaryIndex ? 0 : 1 ),
66 m_wrapperIndexCount( primaryIndex ? 0 : 1 ),
67 m_name( name ),
68 m_dispatcher( *this ) {
69 m_publishFileListTimer = new QTimer( this );
70 connect( m_publishFileListTimer, SIGNAL( timeout() ), this, SLOT( slotPublishFileList() ) );
71 m_publishFileListTimer->setSingleShot( true );
72 m_stateChangeTimer = new QTimer( this );
73 connect( m_stateChangeTimer, SIGNAL( timeout() ), this, SLOT( publishStateChange() ) );
74 m_publishFileListTimer->setSingleShot( true );
76 connect( m_manager, SIGNAL( fillCollaboratingUserMenu( QMenu*, const UserPointer& ) ), this, SLOT( slotFillCollaboratingUserMenu( QMenu*, const UserPointer& ) ) );
78 m_removeUserAction = new QAction( IconCache::getIconStatic( "remove" ), "Remove User", this );
79 connect( m_removeUserAction, SIGNAL( triggered( bool ) ), this, SLOT( removeUserAction() ) );
81 if ( id != 0 )
82 m_id = id;
83 else {
84 QString str = KRandom::randomString( 8 ).toLatin1();
85 m_id = *( ( CollabSessionId* ) & ( str.toAscii().data() [ 0 ] ) ); ///Not a good way of generating a 64-bit random-number..
88 out( Logger::Debug ) << "starting session";
90 for ( CollabFileList::iterator it = files.begin(); it != files.end(); ++it ) {
91 addFileInternal( *it, true, m_isMasterSession );
96 void FileCollaborationSession::slotConnectionResult( FileCollaboration* collab, bool result ) {
97 if ( result && collab->invited() ) {
98 for ( FileSet::Iterator it = m_files.values(); it; ++it ) {
99 synchronizeFile( collab, *it );
103 emit stateChanged( this );
106 void FileCollaborationSession::setAllowSentDocuments( bool allow ) {
107 m_allowSentDocuments = allow;
111 bool FileCollaborationSession::synchronizeFile( const FileCollaborationPointer& collab, const DocumentWrapperPointer& wrapper ) {
112 return wrapper->synchronize( collab->user() );
115 QStringList FileCollaborationSession::plainFileNames() const {
116 QStringList ret;
117 for ( FileSet::ValueMap::const_iterator it = m_files.begin(); it != m_files.end(); ++it )
118 ret << ( *it ).second.value->fileName();
119 return ret;
122 QList<uint> FileCollaborationSession::plainIds() const {
123 QList<uint> ret;
124 for ( FileSet::ValueMap::const_iterator it = m_files.begin(); it != m_files.end(); ++it )
125 ret << ( *it ).second.value->id();
126 return ret;
129 void FileCollaborationSession::removeUserAction() {
130 try {
131 QAction* act = qobject_cast<QAction*>( sender() );
132 if( !act ) throw "no sender-action";
134 QVariant v = act->data();
135 UserPointer u = v.value<UserPointer>();
136 if( !u ) throw "could not get user";
138 FileCollaborationPointer collab = m_collaborations.value( u );
139 if( !collab ) throw "no file-collaboration for the specified user";
141 removeCollaboration( collab );
142 } catch( const char* str ) {
143 err() << "removeUserAction:" << str;
144 } catch( const QString& str ) {
145 err() << "removeUserAction:" << str;
149 void FileCollaborationSession::removeCollaboration( const FileCollaborationPointer& collab ) {
150 collab->close( "goodbye" );
151 m_collaborations.remove( collab );
152 emit stateChanged( this );
156 CollabFileList FileCollaborationSession::fileNames() const {
157 CollabFileList ret;
158 for ( FileSet::ValueMap::const_iterator it = m_files.begin(); it != m_files.end(); ++it ) {
159 ret.push_back( CollabFile( ( *it ).second.value->id(), ( *it ).second.value->fileName() ) );
161 return ret;
164 const FileCollaborationSession::FileSet& FileCollaborationSession::files() const {
165 return m_files;
169 void FileCollaborationSession::fillContextMenu( int /*i*/, QMenu* menu ) {
170 IDocument * d = KDevTeamworkPlugin::staticDocumentController() ->activeDocument();
171 if ( d && d->textDocument() ) {
172 KUrl u = TeamworkFolderManager::workspaceRelative( d->url() );
174 if ( !m_files.values( u.toLocalFile() ) )
175 menu->addAction( "Add Current File", this, SLOT( addFile() ) );
177 QMenu* m = new QMenu( menu );
178 m->setTitle( "Save Result" );
179 m->addAction( "As Files", this, SLOT( saveAsFiles() ) );
180 m->addAction( "As Patch", this, SLOT( saveAsPatch() ) );
181 menu->addSeparator();
182 FileSet::Iterator it = m_files.values();
183 if ( m_isMasterSession && it ) {
184 while ( it && ( *it ) ->dead() )
185 ++it;
186 if ( it ) {
187 if ( ( *it ) ->disabled() )
188 menu->addAction( "Enable Editing", this, SLOT( enableEditing() ) );
189 else
190 menu->addAction( "Disable Editing", this, SLOT( disableEditing() ) );
193 m = new QMenu( menu );
194 m->setTitle( "Remove" );
195 m->addAction( "All Users", this, SLOT( stopSession() ) );
196 m->addAction( "All Files", this, SLOT( removeAllFilesSession() ) );
197 menu->addSeparator();
198 menu->addAction( "Close", this, SLOT( closeSession() ) );
201 bool FileCollaborationSession::acceptMessage( const FileCollaborationRequestPointer& msg ) {
202 try {
203 FileCollaborationRequestPointer::Locked l = msg;
204 if ( !l )
205 throw "could not lock message";
207 KDevTeamworkUserPointer u = l->info().user().cast<KDevTeamworkUser>();
208 if ( !u )
209 throw "message has no user";
211 FileCollaborationPointer collab = newCollaboration( u, msg );
212 if ( !collab )
213 throw "could not create collaboration";
215 return true;
216 } catch ( const QString & str ) {
217 err() << "error in acceptMessage:" << str;
218 return false;
219 } catch ( const char * str ) {
220 err() << "error in acceptMessage:" << str;
221 return false;
223 return false;
226 DocumentWrapperPointer FileCollaborationSession::getDocument( const QString& fileName ) {
227 if ( ! m_files.values( fileName ) ) {
228 out( Logger::Warning ) << "getDocument: Document-wrapper for a file not being collaborated was requested:" << fileName;
229 return 0;
232 return m_files[ fileName ];
235 std::string FileCollaborationSession::logPrefix() {
236 ostringstream str;
237 str << "FileCollaborationSession(" << name() << "," << id() << "): ";
238 return str.str();
241 FileCollaborationPointer FileCollaborationSession::newCollaboration( const KDevTeamworkUserPointer & u, const FileCollaborationRequestPointer& request ) {
242 try {
243 FileCollaborationPointer ret = new FileCollaboration( u, this, request );
244 connect( ret, SIGNAL( connectionResult( FileCollaboration*, bool ) ), this, SLOT( slotConnectionResult( FileCollaboration*, bool ) ) );
245 m_collaborations.insert( ret );
246 return ret;
247 } catch ( const QString & str ) {
248 err() << "error while creating file-collaboration:" << str;
249 return 0;
253 void FileCollaborationSession::updateTree( QModelIndex& i, QStandardItemModel* model ) {
254 QMap<DocumentWrapperPointer, QPersistentModelIndex> positions;
255 QMap<FileCollaborationPointer, QPersistentModelIndex> userPositions;
256 try {
257 if ( model->columnCount( i ) == 0 )
258 model->insertColumn( 0, i );
259 ///Locate all files that are already there
260 for ( int a = model->rowCount( i ) - 1; a >= 0; a-- ) {
261 QModelIndex ind = model->index( a, 0, i );
262 QVariant v = model->data( ind, Qt::UserRole );
263 if ( v.canConvert<CollaborationTreeActionPointer>() ) {
264 StandardCollaborationTreeAction<DocumentWrapper>* d = dynamic_cast< StandardCollaborationTreeAction<DocumentWrapper>* >( v.value<CollaborationTreeActionPointer>().data() );
265 if ( d && d->target ) {
266 if ( m_files.values<DocumentWrapperPointer>( ( DocumentWrapper* ) d->target ) ) {
267 positions[ ( DocumentWrapper* ) d->target ] = ind;
268 } else {
269 ///Remove the old item
270 model->removeRow( a, i );
273 FileCollaborationUserTreeAction * userAction = dynamic_cast< FileCollaborationUserTreeAction* >( v.value<CollaborationTreeActionPointer>().data() );
274 if( userAction ) {
275 if( userAction->target && m_collaborations.value( (FileCollaborationPointer)userAction->target ) ) {
276 ///user is still collaborating
277 userPositions[(FileCollaborationPointer)userAction->target] = ind;
278 } else {
279 ///User must be removed
280 model->removeRow( a, i );
283 } else {
284 model->removeRow( a, i );
285 err() << "unexepected entry-type in tree, removing";
288 ///Add missing files
289 for ( FileSet::ValueMap::iterator it = m_files.begin(); it != m_files.end(); ++it ) {
290 if ( !positions.contains( ( *it ).second.value ) ) {
291 model->insertRow( 0, i ); ///Documents are inserted at the top, users at the bottom.
292 QModelIndex ind = model->index( 0, 0, i );
294 if ( !ind.isValid() )
295 throw "index-error";
296 positions[ ( *it ).second.value ] = ind;
300 ///Add missing users
301 for( CollaborationSet::Iterator it = m_collaborations.values(); it; ++it ) {
302 if ( !userPositions.contains( *it ) ) {
303 int num = model->rowCount( i );
304 model->insertRow( num, i );
305 QModelIndex ind = model->index( num, 0, i );
307 if ( !ind.isValid() )
308 throw "index-error";
309 userPositions[ *it ] = ind;
313 ///Update documents
314 for ( QMap<DocumentWrapperPointer, QPersistentModelIndex>::iterator it = positions.begin(); it != positions.end(); ++it ) {
315 QModelIndex i( *it );
316 const_cast<DocumentWrapperPointer&>( it.key() ) ->updateTree( i, model );
319 ///Update users
320 for ( QMap<FileCollaborationPointer, QPersistentModelIndex>::iterator it = userPositions.begin(); it != userPositions.end(); ++it ) {
321 QModelIndex i(*it);
322 it.key()->updateTree( i , model );
326 } catch ( const char * str ) {
327 err() << "in updateTree:" << str;
328 } catch ( const QString & str ) {
329 err() << "in updateTree:" << str;
333 QIcon FileCollaborationSession::icon() const {
334 if ( state() == Finished )
335 return IconCache::getIconStatic( "collaboration_session_finished" );
336 else {
337 if ( !m_isMasterSession ) {
338 CollaborationSet::Iterator it = m_collaborations.values();
339 if ( !( *it ) ->connectionActive() )
340 return IconCache::getIconStatic( "collaboration_session_connectionlost" );
342 return IconCache::getIconStatic( "collaboration_session" );
346 bool FileCollaborationSession::isMasterSession() const {
347 return m_isMasterSession;
350 uint FileCollaborationSession::primaryIndex() const {
351 return m_primaryIndex;
354 FileCollaborationSession::State FileCollaborationSession::state() const {
355 if ( !m_collaborations.empty() )
356 return Running;
357 return Finished;
360 bool FileCollaborationSession::removeFile( uint id ) {
361 DocumentWrapperPointer wrapper = m_files[ id ];
362 if ( !wrapper )
363 return false;
364 ///@todo ask if content should be saved or if the file should stay completely
365 m_files.remove( wrapper );
367 publishFileRemove( id );
368 m_stateChangeTimer->start( 100 );
369 return true;
372 bool FileCollaborationSession::killFile( uint id ) {
373 DocumentWrapperPointer wrapper = m_files[ id ];
374 if ( !wrapper )
375 return false;
376 ///@todo ask if content should be saved or if the file should stay completely
377 wrapper->setDisabled( true );
378 wrapper->setDead( true );
380 m_stateChangeTimer->start( 100 );
381 return true;
384 uint FileCollaborationSession::addFileInternal( const CollabFile& f, bool fromBuffer, bool readFile ) {
385 try {
386 if ( f.id > m_wrapperIndexCount )
387 m_wrapperIndexCount = f.id + 1;
388 QString file = f.file;
389 /*if ( KDevCore::projectController() ->activeProject() ) {
390 KUrl u( file );
392 if ( u.isParentOf( KDevCore::projectController() ->activeProject() ->projectDirectory() ) ) {
393 QString d = KDevCore::projectController() ->activeProject() ->projectDirectory().toLocalFile();
394 if( !d.endsWith( "/" ) ) d += "/";
395 file = KUrl::relativeUrl( d, u );
399 DocumentWrapperPointer p = new DocumentWrapper( f.id, m_manager->teamwork() ->logger(), file, m_primaryIndex, readFile, this, fromBuffer );
400 connect( p.data(), SIGNAL( publishEdit( const VectorTimestamp&, const SimpleReplacement&, DocumentWrapper* ) ), this, SLOT( publishEdit( const VectorTimestamp&, const SimpleReplacement&, DocumentWrapper* ) ) );
401 m_files.insert( p );
402 m_publishFileListTimer->start( 100 );
403 m_stateChangeTimer->start( 100 );
404 return f.id;
405 } catch ( const QString & str ) {
406 err() << "failed to create document-wrapper for" << f.file << ":" << str;
407 return 0;
411 void FileCollaborationSession::saveAsFiles() {
412 FileSet::Iterator it = m_files.values();
413 while ( it ) {
414 ( *it ) ->saveAsBufferFile();
416 ++it;
420 void FileCollaborationSession::saveAsPatch() {
421 FileSet::Iterator it = m_files.values();
422 QList<LocalPatchSourcePointer> patches;
423 while ( it ) {
425 LocalPatchSourcePointer p = ( *it ) ->saveAsPatch( false, false );
427 ++it;
430 QString patchName = name();
432 if ( !m_isMasterSession ) {
433 CollaborationSet::Iterator it = m_collaborations.values();
434 if ( ( *it ) ->user() )
435 patchName += "@" + ~( *it ) ->user().unsafe() ->safeName() + "_" + QDateTime::currentDateTime().toString( Qt::ISODate );
438 LocalPatchSourcePointer p = manager() ->teamwork() ->patchesManager() ->merge( patchName, patches );
439 if ( p ) {
440 manager() ->teamwork() ->patchesManager() ->addPatch( p );
441 } else {
442 err() << "could not merge the file-patches to one";
445 void FileCollaborationSession::addFile() {
446 try {
447 IDocument * document = KDevTeamworkPlugin::staticDocumentController() ->activeDocument();
448 Q_ASSERT( document != 0 );
449 Q_ASSERT( document->textDocument() != 0 );
451 KUrl u = TeamworkFolderManager::workspaceRelative( document->url() );
453 out( Logger::Debug ) << "adding" << u.toLocalFile() << "to the session";
455 uint index = allocateWrapperIndex();
456 QString fileName = TeamworkFolderManager::teamworkRelative( u );
458 if ( !addFileInternal( CollabFile( index, fileName ), true, true ) )
459 throw "could not add file " + u.toLocalFile();
461 DocumentWrapperPointer wrapper = m_files[ index ];
462 if ( !wrapper )
463 throw "could not get document-wrapper for " + fileName;
465 ///Synchronize the newly created file
466 for ( CollaborationSet::Iterator it = m_collaborations.values(); it; ++it )
467 synchronizeFile( *it, wrapper );
470 } catch ( const QString & str ) {
471 err() << "addFile():" << str;
472 } catch ( const char * str ) {
473 err() << "addFile():" << str;
477 void FileCollaborationSession::stopSession() {
478 out() << "stopping session, disconnecting all users";
479 CollaborationSet::Iterator it = m_collaborations.values();
480 while ( it ) {
481 it.edit() ->data() ->close( "stop" );
482 ++it;
484 m_collaborations.clear();
486 emit stateChanged( this );
489 void FileCollaborationSession::disableEditing() {
490 FileSet::Iterator it = m_files.values();
491 while ( it ) {
492 if ( !( *it ) ->dead() ) {
493 ( *it ) ->setDisabled( true );
495 ++it;
499 void FileCollaborationSession::enableEditing() {
500 FileSet::Iterator it = m_files.values();
501 while ( it ) {
502 if ( !( *it ) ->dead() ) {
503 ( *it ) ->setDisabled( false );
505 ++it;
509 void FileCollaborationSession::removeAllFiles() {
510 FileSet::Iterator it = m_files.values();
511 while ( it ) {
512 removeFile( ( *it ) ->id() );
513 ++it;
517 void FileCollaborationSession::closeSession() {
518 manager() ->closeSession( this );
521 void FileCollaborationSession::publishStateChange() {
522 emit stateChanged( this );
525 QAction* FileCollaborationSession::getRemoveUserAction( const UserPointer& user ) {
526 QVariant v;
527 v.setValue( user );
528 m_removeUserAction->setData( v );
529 return m_removeUserAction;
532 void FileCollaborationSession::publishFileRemove( uint id ) {
533 CollabFileList files = fileNames();
534 files.push_back( CollabFile( id, "" ) );
535 publishFileList( files );
538 void FileCollaborationSession::slotPublishFileList() {
539 publishFileList( fileNames() );
542 void FileCollaborationSession::publishFileList( const CollabFileList& files ) {
543 for ( CollaborationSet::Iterator it = m_collaborations.values(); it; ++it ) {
544 FileCollaborationPointer collab = *it;
545 KDevTeamworkUserPointer::Locked l = collab->user();
546 if ( l ) {
547 if ( l->online().session() ) {
548 globalMessageSendHelper().send<FileListMessage>( l->online().session().unsafe(), files, id() );
550 } else {
551 err() << "publishFileList(..): could not lock user";
556 void FileCollaborationSession::publishEdit( const VectorTimestamp& state, const SimpleReplacement& replacement, DocumentWrapper* sender ) {
557 for ( CollaborationSet::ValueMap::iterator it = m_collaborations.begin(); it != m_collaborations.end(); ++it ) {
558 FileCollaborationPointer collab = ( *it ).second.value;
559 if ( state.primaryIndex() != collab->primaryIndex() ) {
560 KDevTeamworkUserPointer::Locked l = collab->user();
561 if ( l ) {
562 if ( l->online().session() ) {
563 globalMessageSendHelper().send<FileEditMessage>( l->online().session().unsafe(), state, replacement, sender->id(), id() );
565 } else {
566 err() << "publishEdit(..): could not lock user";
572 void FileCollaborationSession::slotFillCollaboratingUserMenu( QMenu * /*menu*/, const UserPointer & /*user*/ ) {}
574 CollabSessionId FileCollaborationSession::id() const {
575 return m_id;
578 QList< KDevTeamworkUserPointer > FileCollaborationSession::users() const {
579 QList<KDevTeamworkUserPointer> ret;
580 for ( CollaborationSet::ValueMap::const_iterator it = m_collaborations.begin(); it != m_collaborations.end(); ++it ) {
581 ret << ( *it ).second.value->user();
583 return ret;
586 void FileCollaborationSession::inviteUser( const KDevTeamworkUserPointer & user ) {
587 try {
588 if ( !m_isMasterSession )
589 throw "cannot invite user to a remote session";
591 KDevTeamworkUserPointer::Locked lu = user;
592 if ( !lu )
593 throw "could not lock user";
595 if ( !lu->online().session() )
596 throw "no session to user " + ~lu->User::name();
598 SessionPointer session = lu->online().session();
600 FileCollaborationPointer collab = newCollaboration( user );
602 } catch ( const char * str ) {
603 err() << "inviteUser:" << str;
604 } catch ( QString str ) {
605 err() << "inviteUser:" << str;
609 QString FileCollaborationSession::firstPeerName() {
610 CollaborationSet::ValueMap::iterator it = m_collaborations.begin();
611 if ( it != m_collaborations.end() ) {
612 KDevTeamworkUserPointer::Locked l = ( *it ).second.value->user();
613 if ( l ) {
614 return ~l->User::name();
615 } else {
616 err() << "firstPeerUserName() could not lock user";
617 return "";
620 return "";
623 uint FileCollaborationSession::allocateIndex() {
624 if ( m_primaryIndex != 0 ) {
625 err() << "allocateIndex() called although session is not master";
627 return m_indexCount++;
630 uint FileCollaborationSession::allocateWrapperIndex() {
631 /*if ( m_primaryIndex != 0 ) {
632 err() << "allocateWrapperIndex() called although session is not master";
635 uint ret = 0;
636 if ( m_isMasterSession )
637 ret = m_wrapperIndexCount++;
638 else
639 ret = m_wrapperIndexCount++ + KRandom::random() % 10 + 5; ///Return a higher number to avoid conflicts
640 if( m_files[ret] )
641 return allocateWrapperIndex();
642 else
643 return ret;
647 void FileCollaborationSession::kickUser( const KDevTeamworkUserPointer & /*user*/ ) {}
649 QString FileCollaborationSession::name() const {
650 return m_name;
653 FileCollaborationManager * FileCollaborationSession::manager() {
654 return m_manager;
657 void FileCollaborationSession::processMessage( const FileCollaborationMessagePointer& msg ) {
658 try {
659 FileCollaborationMessagePointer::Locked lmsg = msg;
660 if ( !lmsg )
661 throw "could not lock message";
663 UserPointer u = lmsg->info().user();
664 if ( !u )
665 throw QString( "no user-information" );
667 FileCollaborationPointer collab = m_collaborations[ u ];
668 if ( !collab )
669 throw ~( "got message from not involved user \"" + u.unsafe() ->safeName() + "\"" );
671 collab->processMessage( msg );
673 } catch ( QString str ) {
674 err() << "could not process message:" << str;
677 int FileCollaborationSession::receiveMessage( MessageInterface* /*msg*/ ) {
678 err() << "got unknown message-type";
679 return 1;
682 int FileCollaborationSession::receiveMessage( FileListMessage* msg ) {
683 for ( CollabFileList::iterator it = msg->m_files.begin(); it != msg->m_files.end(); ++it ) {
684 FileSet::Iterator doc = m_files.values( it->id );
685 if ( doc ) {
686 if ( it->file.isEmpty() ) {
687 if( m_isMasterSession ) {
688 out( Logger::Debug ) << "file" << it->file << "was tried to be removed from the session";
689 } else {
690 out( Logger::Debug ) << "file" << it->file << "has been removed from the session";
691 killFile( it->id );
694 } else {
695 out( Logger::Warning ) << "unknown reference in file-list-message:" << it->id << "" << it->file;
696 /*if ( !it->file.isEmpty() ) {
697 ///Add the new file
698 addFileInternal( *it, false, false );
699 } else {
700 out( Logger::Warning ) << "unknown referenced in file-list-message:" << it->id;
704 return 1;
707 int FileCollaborationSession::receiveMessage( FileCollaborationMessage* msg ) {
708 switch ( msg->message() ) {
709 case FileCollaborationMessageData::CloseSession:
710 if ( !m_isMasterSession ) {
711 out() << "finishing session";
712 aboutToClose();
713 } else {
714 CollaborationSet::Iterator it = m_collaborations.values( msg->info().user() );
715 if ( it ) {
716 it.edit() ->data() ->close( "requested" );
717 m_collaborations.remove( it );
718 } else {
719 err() << "got message from a user that is not part of the collaboration-session";
722 default:
723 out() << "got unhandled file-collaboration-message:" << msg->messageAsString();
725 return 1;
728 int FileCollaborationSession::receiveMessage( DocumentWrapperMessage* msg ) {
729 CollaborationSet::Iterator sender = m_collaborations.values( msg->info().user() );
730 if ( !sender ) {
731 err() << "got FileSynchronize from a not collaborating user";
732 return 0;
735 FileSet::Iterator it = m_files.values<uint>( msg->wrapperId() );
736 if ( it ) {
737 it.edit() ->data() ->processMessage( msg );
738 } else {
739 FileSynchronize* smsg = dynamic_cast<FileSynchronize*>( msg );
740 if ( smsg ) {
741 ///This has to be unterstood as an invitation to add a new document.
742 if ( m_isMasterSession && !m_allowSentDocuments ) {
743 globalMessageSendHelper().sendReply<KDevSystemMessage>( msg, KDevSystemMessage::ActionDenied );
744 QString userName = "anonymous user";
745 if ( msg->info().user() )
746 userName = ~msg->info().user().unsafe() ->safeName();
747 out( Logger::Warning ) << "got a file-synchronization from" << userName << "for \"" << smsg->fileName() << "\", but new files from collaborators are not allowed.";
748 return 1;
750 if ( addFileInternal( CollabFile( smsg->wrapperId(), smsg->fileName() ), false, false ) ) {
751 DocumentWrapperPointer wrapper = m_files[ smsg->wrapperId() ];
752 if ( !wrapper ) {
753 err() << "could not create wrapper";
754 globalMessageSendHelper().sendReply<KDevSystemMessage>( msg, KDevSystemMessage::ActionFailed );
755 return 1;
757 wrapper->processMessage( smsg );
759 if ( m_isMasterSession ) {
760 ///publish the new file to all other clients
761 for ( CollaborationSet::Iterator it = m_collaborations.values(); it; ++it ) {
762 if ( sender == it )
763 continue;
764 synchronizeFile( *it, wrapper );
767 } else {
768 err() << "failed to add file on synchronization:" << smsg->fileName();
769 globalMessageSendHelper().sendReply<KDevSystemMessage>( msg, KDevSystemMessage::ActionFailed );
771 } else {
772 out( Logger::Warning ) << "could not locate the correct document-wrapper for a message of type" << msg->name() << "wrapper-id:" << msg->wrapperId();
775 return 1;
778 int FileCollaborationSession::processMessage( FileCollaborationMessage* msg ) {
779 return m_dispatcher( msg );
782 void FileCollaborationSession::aboutToClose() {
783 stopSession();
786 #include "filecollaborationsession.moc"
789 // kate: space-indent on; indent-width 2; tab-width 2; replace-tabs on