19 #include "editorwatcher.h"
24 #include <tdelocale.h>
25 #include <tdemessagebox.h>
26 #include <kopenwith.h>
27 #include <tdeprocess.h>
28 #include <kuserprofile.h>
30 #include <tqsocketnotifier.h>
35 #ifdef HAVE_SYS_INOTIFY
36 #include <sys/ioctl.h>
37 #include <sys/inotify.h>
40 #include <sys/ioctl.h>
42 #include <sys/inotify.h>
43 #include <sys/syscall.h>
44 #include <linux/types.h>
46 #define _S390_BITOPS_H
49 using namespace KMail;
52 TQObject * parent, TQWidget *parentWidget) :
55 mMimeType( mimeType ),
56 mOpenWith( openWith ),
58 mParentWidget( parentWidget ),
59 mHaveInotify( false ),
61 mEditorRunning( false ),
62 mFileModified( true ),
65 assert( mUrl.isLocalFile() );
66 connect( &mTimer, TQ_SIGNAL(timeout()), TQ_SLOT(checkEditDone()) );
69 bool EditorWatcher::start()
74 KService::Ptr offer = KServiceTypeProfile::preferredService( mMimeType,
"Application" );
75 if ( mOpenWith || !offer ) {
76 KOpenWithDlg dlg( list, i18n(
"Edit with:"), TQString(), 0 );
79 offer = dlg.service();
86 mInotifyFd = inotify_init();
87 if ( mInotifyFd > 0 ) {
88 mInotifyWatch = inotify_add_watch( mInotifyFd, mUrl.path().latin1(), IN_CLOSE | IN_OPEN | IN_MODIFY );
89 if ( mInotifyWatch >= 0 ) {
90 TQSocketNotifier *sn =
new TQSocketNotifier( mInotifyFd, TQSocketNotifier::Read,
this );
91 connect( sn, TQ_SIGNAL(activated(
int)), TQ_SLOT(inotifyEvent()) );
93 mFileModified =
false;
96 kdWarning(5006) << k_funcinfo <<
"Failed to activate INOTIFY!" << endl;
101 TQStringList params = KRun::processDesktopExec( *offer, list,
false );
102 mEditor =
new TDEProcess(
this );
104 connect( mEditor, TQ_SIGNAL(processExited(TDEProcess*)), TQ_SLOT(editorExited()) );
105 if ( !mEditor->start() )
107 mEditorRunning =
true;
113 void EditorWatcher::inotifyEvent()
115 assert( mHaveInotify );
119 ioctl( mInotifyFd, FIONREAD, &pending );
120 while ( pending > 0 ) {
121 int size = read( mInotifyFd, buffer, TQMIN( pending, (
int)
sizeof(buffer) ) );
127 struct inotify_event *
event = (
struct inotify_event *) &buffer[offset];
128 size -=
sizeof(
struct inotify_event ) + event->len;
129 offset +=
sizeof(
struct inotify_event ) + event->len;
130 if ( event->mask & IN_OPEN )
132 if ( event->mask & IN_CLOSE )
134 if ( event->mask & IN_MODIFY )
135 mFileModified =
true;
139 mTimer.start( 500,
true );
143 void EditorWatcher::editorExited()
145 mEditorRunning =
false;
146 mTimer.start( 500,
true );
149 void EditorWatcher::checkEditDone()
151 if ( mEditorRunning || (mFileOpen && mHaveInotify) || mDone )
158 if ( mEditTime.elapsed() <= 3000 ) {
159 KMessageBox::information(
161 i18n(
"KMail is unable to detect when the chosen editor is closed. "
162 "To avoid data loss, editing the attachment will be aborted." ),
163 i18n(
"Unable to edit attachment" ),
164 "UnableToEditAttachment" );
168 emit editDone(
this );
172 #include "editorwatcher.moc"
EditorWatcher(const KURL &url, const TQString &mimeType, bool openWith, TQObject *parent, TQWidget *parentWidget)
Constructs an EditorWatcher.