19#include "editorwatcher.h"
25#include <tdemessagebox.h>
27#include <tdeprocess.h>
28#include <kuserprofile.h>
30#include <tqsocketnotifier.h>
35#ifdef HAVE_SYS_INOTIFY
37#include <sys/inotify.h>
42#include <sys/inotify.h>
43#include <sys/syscall.h>
44#include <linux/types.h>
51EditorWatcher::EditorWatcher(
const KURL & url,
const TQString &mimeType,
bool openWith,
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()) );
69bool 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;
113void 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 );
143void EditorWatcher::editorExited()
145 mEditorRunning =
false;
146 mTimer.start( 500,
true );
149void 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"