comparison MoinMoin/PageGraphicalEditor.py @ 0:77665d8e2254

tag of nonpublic@localhost--archive/moin--enterprise--1.5--base-0 (automatically generated log message) imported from: moin--main--1.5--base-0
author Thomas Waldmann <tw-public@gmx.de>
date Thu, 22 Sep 2005 15:09:50 +0000
parents
children 316340dd9a7f
comparison
equal deleted inserted replaced
-1:000000000000 0:77665d8e2254
1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - Call the GUI editor (FCKeditor)
4
5 @copyright: (c) Bastian Blank, Florian Festi, Thomas Waldmann
6 @license: GNU GPL, see COPYING for details.
7 """
8
9 from MoinMoin import PageEditor
10 import os, time, codecs, re
11
12 from MoinMoin import caching, config, user, util, wikiutil, error
13 from MoinMoin.Page import Page
14 from MoinMoin.widget import html
15 from MoinMoin.widget.dialog import Status
16 from MoinMoin.logfile import editlog, eventlog
17 from MoinMoin.util import filesys
18 import MoinMoin.util.web
19 import MoinMoin.util.mail
20 import MoinMoin.util.datetime
21 from MoinMoin.parser.wiki import Parser
22
23 from StringIO import StringIO
24
25 def execute(pagename, request):
26 if not request.user.may.write(pagename):
27 _ = request.getText
28 Page(request, pagename).send_page(request,
29 msg = _('You are not allowed to edit this page.'))
30 return
31
32 PageGraphicalEditor(request, pagename).sendEditor()
33
34
35 class PageGraphicalEditor(PageEditor.PageEditor):
36
37 def word_rule(self):
38 regex = re.compile(r"\(\?<![^)]*?\)")
39 word_rule = regex.sub("", Parser.word_rule)
40 return repr(word_rule)[1:]
41
42 def sendEditor(self, **kw):
43 """
44 Send the editor form page.
45
46 @keyword preview: if given, show this text in preview mode
47 @keyword staytop: don't go to #preview
48 @keyword comment: comment field (when preview is true)
49 """
50 from MoinMoin import i18n
51 try:
52 from MoinMoin.action import SpellCheck
53 except ImportError:
54 SpellCheck = None
55
56 request = self.request
57 form = self.request.form
58 _ = self._
59 self.request.http_headers(self.request.nocache)
60
61 msg = None
62 conflict_msg = None
63 edit_lock_message = None
64 preview = kw.get('preview', None)
65 staytop = kw.get('staytop', 0)
66
67 # check edit permissions
68 if not self.request.user.may.write(self.page_name):
69 msg = _('You are not allowed to edit this page.')
70 elif not self.isWritable():
71 msg = _('Page is immutable!')
72 elif self.rev:
73 # Trying to edit an old version, this is not possible via
74 # the web interface, but catch it just in case...
75 msg = _('Cannot edit old revisions!')
76 else:
77 # try to acquire edit lock
78 ok, edit_lock_message = self.lock.acquire()
79 if not ok:
80 # failed to get the lock
81 if preview is not None:
82 edit_lock_message = _('The lock you held timed out, be prepared for editing conflicts!'
83 ) + "<br>" + edit_lock_message
84 else:
85 msg = edit_lock_message
86
87 # Did one of the prechecks fail?
88 if msg:
89 self.send_page(self.request, msg=msg)
90 return
91
92 # Check for preview submit
93 if preview is None:
94 title = _('Edit "%(pagename)s"')
95 else:
96 title = _('Preview of "%(pagename)s"')
97 self.set_raw_body(preview, modified=1)
98
99 # send header stuff
100 lock_timeout = self.lock.timeout / 60
101 lock_page = wikiutil.escape(self.page_name, quote=1)
102 lock_expire = _("Your edit lock on %(lock_page)s has expired!") % {'lock_page': lock_page}
103 lock_mins = _("Your edit lock on %(lock_page)s will expire in # minutes.") % {'lock_page': lock_page}
104 lock_secs = _("Your edit lock on %(lock_page)s will expire in # seconds.") % {'lock_page': lock_page}
105
106 # get request parameters
107 try:
108 text_rows = int(form['rows'][0])
109 except StandardError:
110 text_rows = self.cfg.edit_rows
111 if self.request.user.valid:
112 text_rows = int(self.request.user.edit_rows)
113
114 if preview is not None:
115 # Propagate original revision
116 rev = int(form['rev'][0])
117
118 # Check for editing conflicts
119 if not self.exists():
120 # page does not exist, are we creating it?
121 if rev:
122 conflict_msg = _('Someone else deleted this page while you were editing!')
123 elif rev != self.current_rev():
124 conflict_msg = _('Someone else changed this page while you were editing!')
125 if self.mergeEditConflict(rev):
126 conflict_msg = _("""Someone else saved this page while you were editing!
127 Please review the page and save then. Do not save this page as it is!
128 Have a look at the diff of %(difflink)s to see what has been changed.""") % {
129 'difflink': self.link_to(self.request,
130 querystr='action=diff&rev=%d' % rev)
131 }
132 rev = self.current_rev()
133 if conflict_msg:
134 # We don't show preview when in conflict
135 preview = None
136
137 elif self.exists():
138 # revision of existing page
139 rev = self.current_rev()
140 else:
141 # page creation
142 rev = 0
143
144 # Page editing is done using user language
145 self.request.setContentLanguage(self.request.lang)
146
147 # Setup status message
148 status = [kw.get('msg', ''), conflict_msg, edit_lock_message]
149 status = [msg for msg in status if msg]
150 status = ' '.join(status)
151 status = Status(self.request, content=status)
152
153 wikiutil.send_title(self.request,
154 title % {'pagename': self.split_title(self.request),},
155 page=self,
156 pagename=self.page_name, msg=status,
157 body_onload=self.lock.locktype and 'countdown()' or '', # broken / bug in Mozilla 1.5, when using #preview
158 html_head=self.lock.locktype and (
159 PageEditor._countdown_js % {
160 'lock_timeout': lock_timeout,
161 'lock_expire': lock_expire,
162 'lock_mins': lock_mins,
163 'lock_secs': lock_secs,
164 }) or '',
165 editor_mode=1,
166 )
167
168 self.request.write(self.request.formatter.startContent("content"))
169
170 # get the text body for the editor field
171 if form.has_key('template'):
172 # "template" parameter contains the name of the template page
173 template_page = wikiutil.unquoteWikiname(form['template'][0])
174 if self.request.user.may.read(template_page):
175 raw_body = Page(self.request, template_page).get_raw_body()
176 if raw_body:
177 self.request.write(_("[Content of new page loaded from %s]") % (template_page,), '<br>')
178 else:
179 self.request.write(_("[Template %s not found]") % (template_page,), '<br>')
180 else:
181 raw_body = ''
182 self.request.write(_("[You may not read %s]") % (template_page,), '<br>')
183 else:
184 raw_body = self.get_raw_body()
185
186 # Make backup on previews - but not for new empty pages
187 if preview and raw_body:
188 self._make_backup(raw_body)
189
190 # Generate default content for new pages
191 if not raw_body:
192 raw_body = _('Describe %s here.') % (self.page_name,)
193
194 # send text above text area
195 #self.request.write('<p>')
196 #self.request.write(wikiutil.getSysPage(self.request, 'HelpOnFormatting').link_to(self.request))
197 #self.request.write(" | ", wikiutil.getSysPage(self.request, 'InterWiki').link_to(self.request))
198 #if preview is not None and not staytop:
199 # self.request.write(' | <a href="#preview">%s</a>' % _('Skip to preview'))
200 #self.request.write(' ')
201 #self.request.write(_('[current page size \'\'\'%(size)d\'\'\' bytes]') % {'size': self.size()})
202 #self.request.write('</p>')
203
204 # send form
205 self.request.write('<form id="editor" method="post" action="%s/%s#preview">' % (
206 self.request.getScriptname(),
207 wikiutil.quoteWikinameURL(self.page_name),
208 ))
209
210 # yet another weird workaround for broken IE6 (it expands the text
211 # editor area to the right after you begin to type...). IE sucks...
212 # http://fplanque.net/2003/Articles/iecsstextarea/
213 self.request.write('<fieldset style="border:none;padding:0;">')
214
215 self.request.write(unicode(html.INPUT(type="hidden", name="action", value="edit")))
216
217 # Send revision of the page our edit is based on
218 self.request.write('<input type="hidden" name="rev" value="%d">' % (rev,))
219
220 # Save backto in a hidden input
221 backto = form.get('backto', [None])[0]
222 if backto:
223 self.request.write(unicode(html.INPUT(type="hidden", name="backto", value=backto)))
224
225 # button bar
226 button_spellcheck = (SpellCheck and
227 '<input class="button" type="submit" name="button_spellcheck" value="%s">'
228 % _('Check Spelling')) or ''
229
230 save_button_text = _('Save Changes')
231 cancel_button_text = _('Cancel')
232
233 if self.cfg.page_license_enabled:
234 self.request.write('<p><em>', _(
235 """By hitting '''%(save_button_text)s''' you put your changes under the %(license_link)s.
236 If you don't want that, hit '''%(cancel_button_text)s''' to cancel your changes.""") % {
237 'save_button_text': save_button_text,
238 'cancel_button_text': cancel_button_text,
239 'license_link': wikiutil.getSysPage(self.request, self.cfg.page_license_page).link_to(self.request),
240 }, '</em></p>')
241
242 self.request.write('''
243 <input class="button" type="submit" name="button_save" value="%s">
244 <input class="button" type="submit" name="button_preview" value="%s">
245 <input class="button" type="submit" name="button_switch" value="%s">
246 %s
247 <input class="button" type="submit" name="button_cancel" value="%s">
248 <input type="hidden" name="editor" value="gui">
249 ''' % (save_button_text, _('Preview'), _('Text mode'), button_spellcheck, cancel_button_text,))
250
251 # Add textarea with page text
252
253 # TODO: currently self.language is None at this point. We have
254 # to do processing instructions parsing earlier, or move page
255 # language into meta file.
256 lang = self.language or self.request.cfg.default_lang
257 contentlangdirection = i18n.getDirection(lang) # 'ltr' or 'rtl'
258 uilanguage = self.request.lang
259 url_prefix = self.request.cfg.url_prefix
260 wikipage = wikiutil.quoteWikinameURL(self.page_name)
261 fckbasepath = url_prefix + '/applets/FCKeditor'
262 wikiurl = request.getScriptname()
263 if not wikiurl or wikiurl[-1] != '/':
264 wikiurl += '/'
265 themepath = '%s/%s' % (url_prefix, self.request.theme.name)
266 smileypath = themepath + '/img'
267 # auto-generating a list for SmileyImages does NOT work from here!
268 editor_size = int(request.user.edit_rows) * 22 # 22 height_pixels/line
269 word_rule = self.word_rule()
270
271 self.request.write("""
272 <script type="text/javascript" src="%(fckbasepath)s/fckeditor.js"></script>
273 <script type="text/javascript">
274 <!--
275 var oFCKeditor = new FCKeditor( 'savetext', '100%%', %(editor_size)s, 'MoinDefault' ) ;
276 oFCKeditor.BasePath= '%(fckbasepath)s/' ;
277 oFCKeditor.Config['WikiBasePath'] = '%(wikiurl)s' ;
278 oFCKeditor.Config['WikiPage'] = '%(wikipage)s' ;
279 oFCKeditor.Config['PluginsPath'] = '%(url_prefix)s/applets/moinFCKplugins/' ;
280 oFCKeditor.Config['CustomConfigurationsPath'] = '%(url_prefix)s/applets/moinfckconfig.js' ;
281 oFCKeditor.Config['WordRule'] = %(word_rule)s ;
282 oFCKeditor.Config['SmileyPath'] = '%(smileypath)s/' ;
283 oFCKeditor.Config['EditorAreaCSS'] = '%(themepath)s/css/common.css' ;
284 oFCKeditor.Config['SkinPath'] = '%(fckbasepath)s/editor/skins/silver/' ;
285 oFCKeditor.Config['AutoDetectLanguage'] = false ;
286 oFCKeditor.Config['DefaultLanguage'] = '%(uilanguage)s' ;
287 oFCKeditor.Config['ContentLangDirection'] = '%(contentlangdirection)s' ;
288 oFCKeditor.Value= """ % locals())
289
290 from MoinMoin.formatter.text_gedit import Formatter
291 self.formatter = Formatter(request)
292 self.formatter.page = self
293
294 output = StringIO()
295 request.redirect(output)
296 self.send_page_content(request, Parser, raw_body, do_cache=False)
297 request.redirect()
298 output = repr(output.getvalue())
299 if output[0] == 'u':
300 output = output[1:]
301 request.write(output)
302 self.request.write(""" ;
303 oFCKeditor.Create() ;
304 //-->
305 </script>
306 """)
307 self.request.write("<p>")
308 self.request.write(_("Comment:"),
309 ' <input id="editor-comment" type="text" name="comment" value="%s" maxlength="80">' % (
310 wikiutil.escape(kw.get('comment', ''), 1), ))
311 self.request.write("</p>")
312
313 # Category selection
314 filter = re.compile(self.cfg.page_category_regex, re.UNICODE).search
315 cat_pages = self.request.rootpage.getPageList(filter=filter)
316 cat_pages.sort()
317 cat_pages = [wikiutil.pagelinkmarkup(p) for p in cat_pages]
318 cat_pages.insert(0, ('', _('<No addition>', formatted=False)))
319 self.request.write("<p>")
320 self.request.write(_('Add to: %(category)s') % {
321 'category': unicode(util.web.makeSelection('category', cat_pages)),
322 })
323 if self.cfg.mail_smarthost:
324 self.request.write('''
325 &nbsp;
326 <input type="checkbox" name="trivial" id="chktrivial" value="1" %(checked)s>
327 <label for="chktrivial">%(label)s</label> ''' % {
328 'checked': ('', 'checked')[form.get('trivial',['0'])[0] == '1'],
329 'label': _("Trivial change"),
330 })
331
332 self.request.write('''
333 &nbsp;
334 <input type="checkbox" name="rstrip" id="chkrstrip" value="1" %(checked)s>
335 <label for="chkrstrip">%(label)s</label>
336 </p> ''' % {
337 'checked': ('', 'checked')[form.get('rstrip',['0'])[0] == '1'],
338 'label': _('Remove trailing whitespace from each line')
339 })
340
341 self.request.write("</p>")
342
343 badwords_re = None
344 if preview is not None:
345 if SpellCheck and (
346 form.has_key('button_spellcheck') or
347 form.has_key('button_newwords')):
348 badwords, badwords_re, msg = SpellCheck.checkSpelling(self, self.request, own_form=0)
349 self.request.write("<p>%s</p>" % msg)
350 self.request.write('</fieldset>')
351 self.request.write("</form>")
352
353
354 if preview is not None:
355 if staytop:
356 content_id = 'previewbelow'
357 else:
358 content_id = 'preview'
359 self.send_page(self.request, content_id=content_id, content_only=1,
360 hilite_re=badwords_re)
361
362 self.request.write(self.request.formatter.endContent()) # end content div
363 self.request.theme.emit_custom_html(self.cfg.page_footer1)
364 self.request.theme.emit_custom_html(self.cfg.page_footer2)
365