1 /***************************************************************************
2 Copyright 2006 David Nolden <david.nolden.kdevelop@art-master.de>
3 ***************************************************************************/
5 /***************************************************************************
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. *
12 ***************************************************************************/
14 #include "filecollaborationsession.h"
16 Q_DECLARE_METATYPE( Teamwork::UserPointer
)
22 #include <QStandardItemModel>
23 #include <QModelIndex>
25 #include <interfaces/idocumentcontroller.h>
26 #include <interfaces/idocument.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
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:" ),
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 ),
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() ) );
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 {
117 for ( FileSet::ValueMap::const_iterator it
= m_files
.begin(); it
!= m_files
.end(); ++it
)
118 ret
<< ( *it
).second
.value
->fileName();
122 QList
<uint
> FileCollaborationSession::plainIds() const {
124 for ( FileSet::ValueMap::const_iterator it
= m_files
.begin(); it
!= m_files
.end(); ++it
)
125 ret
<< ( *it
).second
.value
->id();
129 void FileCollaborationSession::removeUserAction() {
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 {
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() ) );
164 const FileCollaborationSession::FileSet
& FileCollaborationSession::files() const {
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() )
187 if ( ( *it
) ->disabled() )
188 menu
->addAction( "Enable Editing", this, SLOT( enableEditing() ) );
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
) {
203 FileCollaborationRequestPointer::Locked l
= msg
;
205 throw "could not lock message";
207 KDevTeamworkUserPointer u
= l
->info().user().cast
<KDevTeamworkUser
>();
209 throw "message has no user";
211 FileCollaborationPointer collab
= newCollaboration( u
, msg
);
213 throw "could not create collaboration";
216 } catch ( const QString
& str
) {
217 err() << "error in acceptMessage:" << str
;
219 } catch ( const char * str
) {
220 err() << "error in acceptMessage:" << str
;
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
;
232 return m_files
[ fileName
];
235 std::string
FileCollaborationSession::logPrefix() {
237 str
<< "FileCollaborationSession(" << name() << "," << id() << "): ";
241 FileCollaborationPointer
FileCollaborationSession::newCollaboration( const KDevTeamworkUserPointer
& u
, const FileCollaborationRequestPointer
& request
) {
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
);
247 } catch ( const QString
& str
) {
248 err() << "error while creating file-collaboration:" << str
;
253 void FileCollaborationSession::updateTree( QModelIndex
& i
, QStandardItemModel
* model
) {
254 QMap
<DocumentWrapperPointer
, QPersistentModelIndex
> positions
;
255 QMap
<FileCollaborationPointer
, QPersistentModelIndex
> userPositions
;
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
;
269 ///Remove the old item
270 model
->removeRow( a
, i
);
273 FileCollaborationUserTreeAction
* userAction
= dynamic_cast< FileCollaborationUserTreeAction
* >( v
.value
<CollaborationTreeActionPointer
>().data() );
275 if( userAction
->target
&& m_collaborations
.value( (FileCollaborationPointer
)userAction
->target
) ) {
276 ///user is still collaborating
277 userPositions
[(FileCollaborationPointer
)userAction
->target
] = ind
;
279 ///User must be removed
280 model
->removeRow( a
, i
);
284 model
->removeRow( a
, i
);
285 err() << "unexepected entry-type in tree, removing";
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() )
296 positions
[ ( *it
).second
.value
] = ind
;
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() )
309 userPositions
[ *it
] = ind
;
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
);
320 for ( QMap
<FileCollaborationPointer
, QPersistentModelIndex
>::iterator it
= userPositions
.begin(); it
!= userPositions
.end(); ++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" );
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() )
360 bool FileCollaborationSession::removeFile( uint id
) {
361 DocumentWrapperPointer wrapper
= m_files
[ id
];
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 );
372 bool FileCollaborationSession::killFile( uint id
) {
373 DocumentWrapperPointer wrapper
= m_files
[ id
];
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 );
384 uint
FileCollaborationSession::addFileInternal( const CollabFile
& f
, bool fromBuffer
, bool readFile
) {
386 if ( f
.id
> m_wrapperIndexCount
)
387 m_wrapperIndexCount
= f
.id
+ 1;
388 QString file
= f
.file
;
389 /*if ( KDevCore::projectController() ->activeProject() ) {
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
* ) ) );
402 m_publishFileListTimer
->start( 100 );
403 m_stateChangeTimer
->start( 100 );
405 } catch ( const QString
& str
) {
406 err() << "failed to create document-wrapper for" << f
.file
<< ":" << str
;
411 void FileCollaborationSession::saveAsFiles() {
412 FileSet::Iterator it
= m_files
.values();
414 ( *it
) ->saveAsBufferFile();
420 void FileCollaborationSession::saveAsPatch() {
421 FileSet::Iterator it
= m_files
.values();
422 QList
<LocalPatchSourcePointer
> patches
;
425 LocalPatchSourcePointer p
= ( *it
) ->saveAsPatch( false, false );
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
);
440 manager() ->teamwork() ->patchesManager() ->addPatch( p
);
442 err() << "could not merge the file-patches to one";
445 void FileCollaborationSession::addFile() {
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
];
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();
481 it
.edit() ->data() ->close( "stop" );
484 m_collaborations
.clear();
486 emit
stateChanged( this );
489 void FileCollaborationSession::disableEditing() {
490 FileSet::Iterator it
= m_files
.values();
492 if ( !( *it
) ->dead() ) {
493 ( *it
) ->setDisabled( true );
499 void FileCollaborationSession::enableEditing() {
500 FileSet::Iterator it
= m_files
.values();
502 if ( !( *it
) ->dead() ) {
503 ( *it
) ->setDisabled( false );
509 void FileCollaborationSession::removeAllFiles() {
510 FileSet::Iterator it
= m_files
.values();
512 removeFile( ( *it
) ->id() );
517 void FileCollaborationSession::closeSession() {
518 manager() ->closeSession( this );
521 void FileCollaborationSession::publishStateChange() {
522 emit
stateChanged( this );
525 QAction
* FileCollaborationSession::getRemoveUserAction( const UserPointer
& 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();
547 if ( l
->online().session() ) {
548 globalMessageSendHelper().send
<FileListMessage
>( l
->online().session().unsafe(), files
, id() );
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();
562 if ( l
->online().session() ) {
563 globalMessageSendHelper().send
<FileEditMessage
>( l
->online().session().unsafe(), state
, replacement
, sender
->id(), id() );
566 err() << "publishEdit(..): could not lock user";
572 void FileCollaborationSession::slotFillCollaboratingUserMenu( QMenu
* /*menu*/, const UserPointer
& /*user*/ ) {}
574 CollabSessionId
FileCollaborationSession::id() const {
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();
586 void FileCollaborationSession::inviteUser( const KDevTeamworkUserPointer
& user
) {
588 if ( !m_isMasterSession
)
589 throw "cannot invite user to a remote session";
591 KDevTeamworkUserPointer::Locked lu
= user
;
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();
614 return ~l
->User::name();
616 err() << "firstPeerUserName() could not lock user";
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";
636 if ( m_isMasterSession
)
637 ret
= m_wrapperIndexCount
++;
639 ret
= m_wrapperIndexCount
++ + KRandom::random() % 10 + 5; ///Return a higher number to avoid conflicts
641 return allocateWrapperIndex();
647 void FileCollaborationSession::kickUser( const KDevTeamworkUserPointer
& /*user*/ ) {}
649 QString
FileCollaborationSession::name() const {
653 FileCollaborationManager
* FileCollaborationSession::manager() {
657 void FileCollaborationSession::processMessage( const FileCollaborationMessagePointer& msg ) {
659 FileCollaborationMessagePointer::Locked lmsg = msg;
661 throw "could not lock message";
663 UserPointer u = lmsg->info().user();
665 throw QString( "no user-information" );
667 FileCollaborationPointer collab = m_collaborations[ u ];
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";
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
);
686 if ( it
->file
.isEmpty() ) {
687 if( m_isMasterSession
) {
688 out( Logger::Debug
) << "file" << it
->file
<< "was tried to be removed from the session";
690 out( Logger::Debug
) << "file" << it
->file
<< "has been removed from the session";
695 out( Logger::Warning
) << "unknown reference in file-list-message:" << it
->id
<< "" << it
->file
;
696 /*if ( !it->file.isEmpty() ) {
698 addFileInternal( *it, false, false );
700 out( Logger::Warning ) << "unknown referenced in file-list-message:" << it->id;
707 int FileCollaborationSession::receiveMessage( FileCollaborationMessage
* msg
) {
708 switch ( msg
->message() ) {
709 case FileCollaborationMessageData::CloseSession
:
710 if ( !m_isMasterSession
) {
711 out() << "finishing session";
714 CollaborationSet::Iterator it
= m_collaborations
.values( msg
->info().user() );
716 it
.edit() ->data() ->close( "requested" );
717 m_collaborations
.remove( it
);
719 err() << "got message from a user that is not part of the collaboration-session";
723 out() << "got unhandled file-collaboration-message:" << msg
->messageAsString();
728 int FileCollaborationSession::receiveMessage( DocumentWrapperMessage
* msg
) {
729 CollaborationSet::Iterator sender
= m_collaborations
.values( msg
->info().user() );
731 err() << "got FileSynchronize from a not collaborating user";
735 FileSet::Iterator it
= m_files
.values
<uint
>( msg
->wrapperId() );
737 it
.edit() ->data() ->processMessage( msg
);
739 FileSynchronize
* smsg
= dynamic_cast<FileSynchronize
*>( msg
);
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.";
750 if ( addFileInternal( CollabFile( smsg
->wrapperId(), smsg
->fileName() ), false, false ) ) {
751 DocumentWrapperPointer wrapper
= m_files
[ smsg
->wrapperId() ];
753 err() << "could not create wrapper";
754 globalMessageSendHelper().sendReply
<KDevSystemMessage
>( msg
, KDevSystemMessage::ActionFailed
);
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
) {
764 synchronizeFile( *it
, wrapper
);
768 err() << "failed to add file on synchronization:" << smsg
->fileName();
769 globalMessageSendHelper().sendReply
<KDevSystemMessage
>( msg
, KDevSystemMessage::ActionFailed
);
772 out( Logger::Warning
) << "could not locate the correct document-wrapper for a message of type" << msg
->name() << "wrapper-id:" << msg
->wrapperId();
778 int FileCollaborationSession::processMessage( FileCollaborationMessage
* msg
) {
779 return m_dispatcher( msg
);
782 void FileCollaborationSession::aboutToClose() {
786 #include "filecollaborationsession.moc"
789 // kate: space-indent on; indent-width 2; tab-width 2; replace-tabs on