2
from ReText.htmldialog import HtmlDialog
3
from ReText.highlighter import ReTextHighlighter
5
class ReTextWindow(QMainWindow):
6
def __init__(self, parent=None):
7
QMainWindow.__init__(self, parent)
9
screen = QDesktopWidget().screenGeometry()
10
size = self.geometry()
11
self.move((screen.width()-size.width())/2, (screen.height()-size.height())/2)
12
if settings.contains('iconTheme'):
13
QIcon.setThemeName(readFromSettings(settings, 'iconTheme', str))
14
if QIcon.themeName() in ('', 'hicolor'):
16
gconf = Popen(['gconftool-2', '--get', '/desktop/gnome/interface/icon_theme'],
20
iconTheme = gconf.stdout.read().rstrip()
21
if iconTheme: QIcon.setThemeName(iconTheme.decode())
22
if settings.contains('font'):
23
self.font = QFont(readFromSettings(settings, 'font', str))
24
if settings.contains('fontSize'):
25
self.font.setPointSize(readFromSettings(settings, 'fontSize', int))
28
if settings.contains('tabWidth'):
29
self.tabWidth = readFromSettings(settings, 'tabWidth', int)
32
if settings.contains('tabInsertsSpaces'):
33
self.tabInsertsSpaces = readFromSettings(settings, 'tabInsertsSpaces', bool)
35
self.tabInsertsSpaces = False
36
if QFile.exists(icon_path+'retext.png'):
37
self.setWindowIcon(QIcon(icon_path+'retext.png'))
39
self.setWindowIcon(QIcon.fromTheme('retext', QIcon.fromTheme('accessories-text-editor')))
41
self.previewBoxes = []
42
self.highlighters = []
48
self.tabWidget = QTabWidget(self)
49
self.tabWidget.setTabsClosable(True)
50
self.setCentralWidget(self.tabWidget)
51
self.connect(self.tabWidget, SIGNAL('currentChanged(int)'), self.changeIndex)
52
self.connect(self.tabWidget, SIGNAL('tabCloseRequested(int)'), self.closeTab)
53
self.toolBar = QToolBar(self.tr('File toolbar'), self)
54
self.addToolBar(Qt.TopToolBarArea, self.toolBar)
55
self.editBar = QToolBar(self.tr('Edit toolbar'), self)
56
self.addToolBar(Qt.TopToolBarArea, self.editBar)
57
self.searchBar = QToolBar(self.tr('Search toolbar'), self)
58
self.addToolBar(Qt.BottomToolBarArea, self.searchBar)
59
self.actionNew = self.act(self.tr('New'), icon='document-new', shct=QKeySequence.New, trig=self.createNew)
60
self.actionNew.setPriority(QAction.LowPriority)
61
self.actionOpen = self.act(self.tr('Open'), icon='document-open', shct=QKeySequence.Open, trig=self.openFile)
62
self.actionOpen.setPriority(QAction.LowPriority)
63
self.actionSave = self.act(self.tr('Save'), icon='document-save', shct=QKeySequence.Save, trig=self.saveFile)
64
self.actionSave.setEnabled(False)
65
self.actionSave.setPriority(QAction.LowPriority)
66
self.actionSaveAs = self.act(self.tr('Save as'), icon='document-save-as', shct=QKeySequence.SaveAs,
68
self.actionPrint = self.act(self.tr('Print'), icon='document-print', shct=QKeySequence.Print, trig=self.printFile)
69
self.actionPrint.setPriority(QAction.LowPriority)
70
self.actionPrintPreview = self.act(self.tr('Print preview'), icon='document-print-preview',
71
trig=self.printPreview)
72
self.actionViewHtml = self.act(self.tr('View HTML code'), icon='text-html', trig=self.viewHtml)
73
self.actionChangeFont = self.act(self.tr('Change default font'), trig=self.changeFont)
74
self.actionSearch = self.act(self.tr('Find text'), icon='edit-find', shct=QKeySequence.Find)
75
self.actionSearch.setCheckable(True)
76
self.connect(self.actionSearch, SIGNAL('triggered(bool)'), self.searchBar, SLOT('setVisible(bool)'))
77
self.connect(self.searchBar, SIGNAL('visibilityChanged(bool)'), self.searchBarVisibilityChanged)
78
self.actionPreview = self.act(self.tr('Preview'), shct=Qt.CTRL+Qt.Key_E, trigbool=self.preview)
79
if QIcon.hasThemeIcon('document-preview'):
80
self.actionPreview.setIcon(QIcon.fromTheme('document-preview'))
81
elif QIcon.hasThemeIcon('preview-file'):
82
self.actionPreview.setIcon(QIcon.fromTheme('preview-file'))
83
elif QIcon.hasThemeIcon('x-office-document'):
84
self.actionPreview.setIcon(QIcon.fromTheme('x-office-document'))
86
self.actionPreview.setIcon(QIcon(icon_path+'document-preview.png'))
87
self.actionLivePreview = self.act(self.tr('Live preview'), shct=Qt.CTRL+Qt.Key_L,
88
trigbool=self.enableLivePreview)
89
self.actionFullScreen = self.act(self.tr('Fullscreen mode'), icon='view-fullscreen', shct=Qt.Key_F11,
90
trigbool=self.enableFullScreen)
91
self.actionPerfectHtml = self.act('HTML', icon='text-html', trig=self.saveFilePerfect)
92
self.actionPdf = self.act('PDF', icon='application-pdf', trig=self.savePdf)
93
self.actionOdf = self.act('ODT', icon='x-office-document', trig=self.saveOdf)
94
self.getExportExtensionsList()
95
self.actionQuit = self.act(self.tr('Quit'), icon='application-exit', shct=QKeySequence.Quit)
96
self.actionQuit.setMenuRole(QAction.QuitRole)
97
self.connect(self.actionQuit, SIGNAL('triggered()'), self.close)
98
self.actionUndo = self.act(self.tr('Undo'), icon='edit-undo', shct=QKeySequence.Undo,
99
trig=lambda: self.editBoxes[self.ind].undo())
100
self.actionRedo = self.act(self.tr('Redo'), icon='edit-redo', shct=QKeySequence.Redo,
101
trig=lambda: self.editBoxes[self.ind].redo())
102
self.actionCopy = self.act(self.tr('Copy'), icon='edit-copy', shct=QKeySequence.Copy,
103
trig=lambda: self.editBoxes[self.ind].copy())
104
self.actionCut = self.act(self.tr('Cut'), icon='edit-cut', shct=QKeySequence.Cut,
105
trig=lambda: self.editBoxes[self.ind].cut())
106
self.actionPaste = self.act(self.tr('Paste'), icon='edit-paste', shct=QKeySequence.Paste,
107
trig=lambda: self.editBoxes[self.ind].paste())
108
self.actionUndo.setEnabled(False)
109
self.actionRedo.setEnabled(False)
110
self.actionCopy.setEnabled(False)
111
self.actionCut.setEnabled(False)
112
self.connect(qApp.clipboard(), SIGNAL('dataChanged()'), self.clipboardDataChanged)
113
self.clipboardDataChanged()
114
if enchant_available:
115
self.actionEnableSC = self.act(self.tr('Enable'), trigbool=self.enableSC)
116
self.actionSetLocale = self.act(self.tr('Set locale'), trig=self.changeLocale)
117
self.actionPlainText = self.act(self.tr('Plain text'), trigbool=self.enablePlainText)
119
self.actionWebKit = self.act(self.tr('Use WebKit renderer'), trigbool=self.enableWebKit)
120
self.useWebKit = False
121
if settings.contains('useWebKit'):
122
if readFromSettings(settings, 'useWebKit', bool):
123
self.useWebKit = True
124
self.actionWebKit.setChecked(True)
126
self.actionWpgen = self.act(self.tr('Generate webpages'), trig=self.startWpgen)
127
self.actionShow = self.act(self.tr('Show'), icon='system-file-manager', trig=self.showInDir)
128
self.actionFind = self.act(self.tr('Next'), icon='go-next', shct=QKeySequence.FindNext, trig=self.find)
129
self.actionFindPrev = self.act(self.tr('Previous'), icon='go-previous', shct=QKeySequence.FindPrevious,
130
trig=lambda: self.find(back=True))
131
self.actionHelp = self.act(self.tr('Get help online'), icon='help-contents', trig=self.openHelp)
133
self.aboutWindowTitle = self.tr('About %s') % app_name
136
self.aboutWindowTitle = self.tr('About %s').replace('%s', '%1').arg(app_name)
137
self.actionAbout = self.act(self.aboutWindowTitle, icon='help-about', trig=self.aboutDialog)
138
self.actionAbout.setMenuRole(QAction.AboutRole)
139
self.actionAboutQt = self.act(self.tr('About Qt'))
140
self.actionAboutQt.setMenuRole(QAction.AboutQtRole)
141
self.connect(self.actionAboutQt, SIGNAL('triggered()'), qApp, SLOT('aboutQt()'))
142
availableMarkups = markups.get_available_markups()
143
if not availableMarkups:
144
print('Warning: no markups are available!')
145
self.defaultMarkup = availableMarkups[0] if availableMarkups else None
146
if settings.contains('defaultMarkup'):
147
dm = str(readFromSettings(settings, 'defaultMarkup', str))
148
mc = markups.find_markup_class_by_name(dm)
149
if mc and mc.available():
150
self.defaultMarkup = mc
151
if len(availableMarkups) > 1:
152
self.chooseGroup = QActionGroup(self)
154
for markup in availableMarkups:
155
markupAction = self.act(markup.name, trigbool=self.markupFunction(markup))
156
if markup == self.defaultMarkup:
157
markupAction.setChecked(True)
158
self.chooseGroup.addAction(markupAction)
159
markupActions.append(markupAction)
160
self.actionBold = self.act(self.tr('Bold'), shct=QKeySequence.Bold, trig=lambda: self.insertChars('**'))
161
self.actionItalic = self.act(self.tr('Italic'), shct=QKeySequence.Italic, trig=lambda: self.insertChars('*'))
162
self.actionUnderline = self.act(self.tr('Underline'), shct=QKeySequence.Underline,
163
trig=lambda: self.insertTag(9)) # <u>...</u>
164
self.usefulTags = ('big', 'center', 's', 'small', 'span', 'table', 'td', 'tr', 'u')
165
self.usefulChars = ('deg', 'divide', 'hellip', 'laquo', 'larr',
166
'lsquo', 'mdash', 'middot', 'minus', 'nbsp', 'ndash', 'raquo',
167
'rarr', 'rsquo', 'times')
168
self.tagsBox = QComboBox(self.editBar)
169
self.tagsBox.addItem(self.tr('Tags'))
170
self.tagsBox.addItems(self.usefulTags)
171
self.connect(self.tagsBox, SIGNAL('activated(int)'), self.insertTag)
172
self.symbolBox = QComboBox(self.editBar)
173
self.symbolBox.addItem(self.tr('Symbols'))
174
self.symbolBox.addItems(self.usefulChars)
175
self.connect(self.symbolBox, SIGNAL('activated(int)'), self.insertSymbol)
176
if settings.contains('styleSheet'):
177
ssname = readFromSettings(settings, 'styleSheet', str)
178
sheetfile = QFile(ssname)
179
sheetfile.open(QIODevice.ReadOnly)
180
self.ss = QTextStream(sheetfile).readAll()
184
self.menubar = QMenuBar(self)
185
self.menubar.setGeometry(QRect(0, 0, 800, 25))
186
self.setMenuBar(self.menubar)
187
self.menuFile = self.menubar.addMenu(self.tr('File'))
188
self.menuEdit = self.menubar.addMenu(self.tr('Edit'))
189
self.menuHelp = self.menubar.addMenu(self.tr('Help'))
190
self.menuFile.addAction(self.actionNew)
191
self.menuFile.addAction(self.actionOpen)
192
self.menuRecentFiles = self.menuFile.addMenu(self.tr('Open recent'))
193
self.connect(self.menuRecentFiles, SIGNAL('aboutToShow()'), self.updateRecentFiles)
194
self.menuFile.addMenu(self.menuRecentFiles)
195
self.menuDir = self.menuFile.addMenu(self.tr('Directory'))
196
self.menuDir.addAction(self.actionShow)
198
self.menuDir.addAction(self.actionWpgen)
199
self.menuFile.addSeparator()
200
self.menuFile.addAction(self.actionSave)
201
self.menuFile.addAction(self.actionSaveAs)
202
self.menuFile.addSeparator()
203
self.menuExport = self.menuFile.addMenu(self.tr('Export'))
204
self.menuExport.addAction(self.actionPerfectHtml)
205
self.menuExport.addAction(self.actionOdf)
206
self.menuExport.addAction(self.actionPdf)
207
if self.extensionActions:
208
self.menuExport.addSeparator()
209
for action, mimetype in self.extensionActions:
210
self.menuExport.addAction(action)
211
self.connect(self.menuRecentFiles, SIGNAL('aboutToShow()'), self.updateExtensionsVisibility)
212
self.menuFile.addAction(self.actionPrint)
213
self.menuFile.addAction(self.actionPrintPreview)
214
self.menuFile.addSeparator()
215
self.menuFile.addAction(self.actionQuit)
216
self.menuEdit.addAction(self.actionUndo)
217
self.menuEdit.addAction(self.actionRedo)
218
self.menuEdit.addSeparator()
219
self.menuEdit.addAction(self.actionCut)
220
self.menuEdit.addAction(self.actionCopy)
221
self.menuEdit.addAction(self.actionPaste)
222
self.menuEdit.addSeparator()
224
if enchant_available:
225
self.menuSC = self.menuEdit.addMenu(self.tr('Spell check'))
226
self.menuSC.addAction(self.actionEnableSC)
227
self.menuSC.addAction(self.actionSetLocale)
228
self.menuEdit.addAction(self.actionSearch)
229
self.menuEdit.addAction(self.actionPlainText)
230
self.menuEdit.addAction(self.actionChangeFont)
231
self.menuEdit.addSeparator()
232
if len(availableMarkups) > 1:
233
self.menuMode = self.menuEdit.addMenu(self.tr('Default editing mode'))
234
for markupAction in markupActions:
235
self.menuMode.addAction(markupAction)
236
self.menuFormat = self.menuEdit.addMenu(self.tr('Formatting'))
237
self.menuFormat.addAction(self.actionBold)
238
self.menuFormat.addAction(self.actionItalic)
239
self.menuFormat.addAction(self.actionUnderline)
241
self.menuEdit.addAction(self.actionWebKit)
242
self.menuEdit.addSeparator()
243
self.menuEdit.addAction(self.actionViewHtml)
244
self.menuEdit.addAction(self.actionLivePreview)
245
self.menuEdit.addAction(self.actionPreview)
246
self.menuEdit.addSeparator()
247
self.menuEdit.addAction(self.actionFullScreen)
248
self.menuHelp.addAction(self.actionHelp)
249
self.menuHelp.addSeparator()
250
self.menuHelp.addAction(self.actionAbout)
251
self.menuHelp.addAction(self.actionAboutQt)
252
self.menubar.addMenu(self.menuFile)
253
self.menubar.addMenu(self.menuEdit)
254
self.menubar.addMenu(self.menuHelp)
255
self.toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
256
self.toolBar.addAction(self.actionNew)
257
self.toolBar.addSeparator()
258
self.toolBar.addAction(self.actionOpen)
259
self.toolBar.addAction(self.actionSave)
260
self.toolBar.addAction(self.actionPrint)
261
self.toolBar.addSeparator()
262
self.toolBar.addAction(self.actionPreview)
263
self.editBar.addAction(self.actionUndo)
264
self.editBar.addAction(self.actionRedo)
265
self.editBar.addSeparator()
266
self.editBar.addAction(self.actionCut)
267
self.editBar.addAction(self.actionCopy)
268
self.editBar.addAction(self.actionPaste)
269
self.editBar.addSeparator()
270
self.editBar.addWidget(self.tagsBox)
271
self.editBar.addWidget(self.symbolBox)
272
self.searchEdit = QLineEdit(self.searchBar)
274
self.searchEdit.setPlaceholderText(self.tr('Search'))
276
self.connect(self.searchEdit, SIGNAL('returnPressed()'), self.find)
277
self.csBox = QCheckBox(self.tr('Case sensitively'), self.searchBar)
278
self.searchBar.addWidget(self.searchEdit)
279
self.searchBar.addWidget(self.csBox)
280
self.searchBar.addAction(self.actionFindPrev)
281
self.searchBar.addAction(self.actionFind)
282
self.searchBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
283
self.searchBar.setVisible(False)
284
self.autoSave = False
285
if settings.contains('autoSave'):
286
if readFromSettings(settings, 'autoSave', bool):
290
self.connect(timer, SIGNAL('timeout()'), self.saveAll)
291
self.restorePreviewState = False
292
self.livePreviewEnabled = False
293
if settings.contains('restorePreviewState'):
294
self.restorePreviewState = readFromSettings(settings, 'restorePreviewState', bool)
295
if settings.contains('previewState'):
296
self.livePreviewEnabled = readFromSettings(settings, 'previewState', bool)
298
self.tabWidget.addTab(self.createTab(""), self.tr('New document'))
299
if enchant_available:
301
if settings.contains('spellCheckLocale'):
303
self.sl = str(readFromSettings(settings, 'spellCheckLocale', str))
304
enchant.Dict(self.sl)
305
except Exception as e:
308
if settings.contains('spellCheck'):
309
if readFromSettings(settings, 'spellCheck', bool):
310
self.actionEnableSC.setChecked(True)
313
def act(self, name, icon=None, trig=None, trigbool=None, shct=None):
315
action = QAction(self.actIcon(icon), name, self)
317
action = QAction(name, self)
319
self.connect(action, SIGNAL('triggered()'), trig)
321
action.setCheckable(True)
322
self.connect(action, SIGNAL('triggered(bool)'), trigbool)
324
action.setShortcut(shct)
327
def actIcon(self, name):
328
return QIcon.fromTheme(name, QIcon(icon_path+name+'.png'))
330
def printError(self, error):
331
print('Exception occured while parsing document:')
334
def getSplitter(self, index):
335
splitter = QSplitter(Qt.Horizontal)
336
# Give both boxes a minimum size so the minimumSizeHint will be
337
# ignored when splitter.setSizes is called below
338
for widget in self.editBoxes[index], self.previewBoxes[index]:
339
widget.setMinimumWidth(125)
340
splitter.addWidget(widget)
341
splitter.setSizes((50, 50))
342
splitter.setChildrenCollapsible(False)
345
def createTab(self, fileName):
346
self.previewBlocked = False
347
self.editBoxes.append(QTextEdit())
348
self.highlighters.append(ReTextHighlighter(self.editBoxes[-1].document()))
349
if enchant_available and self.actionEnableSC.isChecked():
350
self.highlighters[-1].dictionary = \
351
enchant.Dict(self.sl) if self.sl else enchant.Dict()
352
self.highlighters[-1].rehighlight()
354
self.previewBoxes.append(QWebView())
356
self.previewBoxes.append(QTextEdit())
357
self.previewBoxes[-1].setReadOnly(True)
358
self.editBoxes[-1].contextMenuEvent = self.editBoxMenuEvent
359
if self.tabInsertsSpaces:
360
self.editBoxes[-1].keyPressEvent = self.editBoxKeyPressEvent
361
self.previewBoxes[-1].setVisible(False)
362
self.fileNames.append(fileName)
363
markupClass = self.getMarkupClass(fileName)
364
self.markups.append(self.getMarkup(fileName))
365
self.highlighters[-1].docType = (markupClass.name if markupClass else '')
366
liveMode = self.restorePreviewState and self.livePreviewEnabled
367
self.apc.append(liveMode)
368
self.alpc.append(liveMode)
369
self.aptc.append(False)
370
self.editBoxes[-1].setFont(monofont)
371
metrics = QFontMetrics(self.editBoxes[-1].font())
372
self.editBoxes[-1].setTabStopWidth(self.tabWidth*metrics.width(' '))
373
self.editBoxes[-1].setAcceptRichText(False)
374
self.connect(self.editBoxes[-1], SIGNAL('textChanged()'), self.updateLivePreviewBox)
375
self.connect(self.editBoxes[-1], SIGNAL('undoAvailable(bool)'), self.actionUndo, SLOT('setEnabled(bool)'))
376
self.connect(self.editBoxes[-1], SIGNAL('redoAvailable(bool)'), self.actionRedo, SLOT('setEnabled(bool)'))
377
self.connect(self.editBoxes[-1], SIGNAL('copyAvailable(bool)'), self.enableCopy)
378
self.connect(self.editBoxes[-1].document(), SIGNAL('modificationChanged(bool)'), self.modificationChanged)
379
return self.getSplitter(-1)
381
def editBoxMenuEvent(self, event):
382
editBox = self.editBoxes[self.ind]
383
text = editBox.toPlainText()
384
dictionary = self.highlighters[self.ind].dictionary
385
if dictionary is None or not text:
386
return QTextEdit.contextMenuEvent(editBox, event)
387
oldcursor = editBox.textCursor()
388
cursor = editBox.cursorForPosition(event.pos())
389
pos = cursor.positionInBlock()
390
if pos == len(text): pos -= 1
393
isalpha = curchar.isalpha()
394
except AttributeError:
396
curchar = text.at(pos)
397
isalpha = curchar.isLetter()
399
return QTextEdit.contextMenuEvent(editBox, event)
400
cursor.select(QTextCursor.WordUnderCursor)
401
editBox.setTextCursor(cursor)
402
word = convertToUnicode(cursor.selectedText())
403
if not word or dictionary.check(word):
404
editBox.setTextCursor(oldcursor)
405
return QTextEdit.contextMenuEvent(editBox, event)
406
suggestions = dictionary.suggest(word)
407
actions = [self.act(sug, trig=self.fixWord(sug)) for sug in suggestions]
408
menu = editBox.createStandardContextMenu()
409
menu.insertSeparator(menu.actions()[0])
410
for action in actions[::-1]:
411
menu.insertAction(menu.actions()[0], action)
412
menu.exec_(event.globalPos())
414
def fixWord(self, correctword):
415
return lambda: self.editBoxes[self.ind].insertPlainText(correctword)
417
def editBoxKeyPressEvent(self, event):
419
if key == Qt.Key_Tab:
420
self.editBoxIndentMore(self.editBoxes[self.ind])
421
elif key == Qt.Key_Backtab:
422
self.editBoxIndentLess(self.editBoxes[self.ind])
424
QTextEdit.keyPressEvent(self.editBoxes[self.ind], event)
426
def editBoxIndentMore(self, editBox):
427
cursor = editBox.textCursor()
428
if cursor.hasSelection():
429
block = editBox.document().findBlock(cursor.selectionStart())
430
end = editBox.document().findBlock(cursor.selectionEnd()).next()
431
cursor.beginEditBlock()
433
cursor.setPosition(block.position())
434
cursor.insertText(' ' * self.tabWidth)
436
cursor.endEditBlock()
438
indent = self.tabWidth - (cursor.positionInBlock() % self.tabWidth)
439
cursor.insertText(' ' * indent)
441
def editBoxIndentLess(self, editBox):
442
cursor = editBox.textCursor()
443
if cursor.hasSelection():
444
block = editBox.document().findBlock(cursor.selectionStart())
445
end = editBox.document().findBlock(cursor.selectionEnd()).next()
447
block = editBox.document().findBlock(cursor.position())
449
cursor.beginEditBlock()
451
cursor.setPosition(block.position())
453
while editBox.document().characterAt(cursor.position()) == ' ' \
454
and pos < self.tabWidth:
458
cursor.endEditBlock()
460
def closeTab(self, ind):
461
if self.maybeSave(ind):
462
if self.tabWidget.count() == 1:
463
self.tabWidget.addTab(self.createTab(""), self.tr("New document"))
464
del self.editBoxes[ind]
465
del self.previewBoxes[ind]
466
del self.highlighters[ind]
467
del self.markups[ind]
468
del self.fileNames[ind]
472
self.tabWidget.removeTab(ind)
474
def getMarkupClass(self, fileName=None):
476
fileName = self.fileNames[self.ind]
477
fileName = convertToUnicode(fileName)
478
if self.actionPlainText.isChecked():
481
markupClass = markups.get_markup_for_file_name(
482
fileName, return_class=True)
485
return self.defaultMarkup
487
def getMarkup(self, fileName=None):
489
fileName = self.fileNames[self.ind]
490
fileName = convertToUnicode(fileName)
491
markupClass = self.getMarkupClass(fileName=fileName)
492
if markupClass and markupClass.available():
493
return markupClass(filename=fileName)
495
def docTypeChanged(self):
496
self.markups[self.ind] = self.getMarkup()
497
oldType = self.highlighters[self.ind].docType
498
markupClass = self.getMarkupClass()
499
newType = markupClass.name if markupClass else ''
500
if oldType != newType:
501
self.updatePreviewBox()
502
self.highlighters[self.ind].docType = newType
503
self.highlighters[self.ind].rehighlight()
504
dtMarkdown = (newType == DOCTYPE_MARKDOWN)
505
dtMkdOrReST = (newType in (DOCTYPE_MARKDOWN, DOCTYPE_REST))
506
self.tagsBox.setEnabled(dtMarkdown)
507
self.symbolBox.setEnabled(dtMarkdown)
508
self.actionUnderline.setEnabled(dtMarkdown)
509
self.actionBold.setEnabled(dtMkdOrReST)
510
self.actionItalic.setEnabled(dtMkdOrReST)
512
def changeIndex(self, ind):
514
self.actionPlainText.setChecked(self.aptc[ind])
515
self.actionPerfectHtml.setDisabled(self.aptc[ind])
516
self.actionViewHtml.setDisabled(self.aptc[ind])
517
self.actionUndo.setEnabled(self.editBoxes[ind].document().isUndoAvailable())
518
self.actionRedo.setEnabled(self.editBoxes[ind].document().isRedoAvailable())
519
self.actionCopy.setEnabled(self.editBoxes[ind].textCursor().hasSelection())
520
self.actionCut.setEnabled(self.editBoxes[ind].textCursor().hasSelection())
521
self.actionPreview.setChecked(self.apc[ind])
522
self.actionLivePreview.setChecked(self.alpc[ind])
523
self.editBar.setDisabled(self.apc[ind])
525
if self.fileNames[ind]:
526
self.setCurrentFile()
529
self.setWindowTitle(self.tr('New document') + '[*] ' + QChar(0x2014) + ' ' + app_name)
532
self.setWindowTitle(self.tr('New document') + '[*] \u2014 ' + app_name)
533
self.modificationChanged(self.editBoxes[ind].document().isModified())
534
self.livePreviewEnabled = self.alpc[ind]
536
self.enableLivePreview(True)
537
self.editBoxes[self.ind].setFocus(Qt.OtherFocusReason)
539
def changeFont(self):
542
fd = QFontDialog.getFont(self.font, self)
545
self.font.setFamily(fd[0].family())
546
settings.setValue('font', fd[0].family())
547
self.font.setPointSize(fd[0].pointSize())
548
settings.setValue('fontSize', fd[0].pointSize())
549
self.updatePreviewBox()
551
def preview(self, viewmode):
552
self.apc[self.ind] = viewmode
553
if self.actionLivePreview.isChecked():
554
self.actionLivePreview.setChecked(False)
555
return self.enableLivePreview(False)
556
self.editBar.setDisabled(viewmode)
557
self.editBoxes[self.ind].setVisible(not viewmode)
558
self.previewBoxes[self.ind].setVisible(viewmode)
560
self.updatePreviewBox()
562
def enableLivePreview(self, livemode):
563
self.livePreviewEnabled = livemode
564
self.alpc[self.ind] = livemode
565
self.apc[self.ind] = livemode
566
self.actionPreview.setChecked(livemode)
567
self.editBar.setEnabled(True)
568
self.previewBoxes[self.ind].setVisible(livemode)
569
self.editBoxes[self.ind].setVisible(True)
571
self.updatePreviewBox()
573
def enableWebKit(self, enable):
574
self.useWebKit = enable
576
settings.setValue('useWebKit', True)
578
settings.remove('useWebKit')
580
self.tabWidget.clear()
581
for self.ind in range(len(self.editBoxes)):
583
self.previewBoxes[self.ind] = QWebView()
585
self.previewBoxes[self.ind] = QTextEdit()
586
self.previewBoxes[self.ind].setReadOnly(True)
587
splitter = self.getSplitter(self.ind)
588
self.tabWidget.addTab(splitter, self.getDocumentTitle(baseName=True))
589
self.updatePreviewBox()
590
self.previewBoxes[self.ind].setVisible(self.apc[self.ind])
592
self.tabWidget.setCurrentIndex(self.ind)
594
def enableCopy(self, copymode):
595
self.actionCopy.setEnabled(copymode)
596
self.actionCut.setEnabled(copymode)
598
def enableFullScreen(self, yes):
600
self.showFullScreen()
604
def enableSC(self, yes):
607
self.setAllDictionaries(enchant.Dict(self.sl))
609
self.setAllDictionaries(enchant.Dict())
610
settings.setValue('spellCheck', True)
612
self.setAllDictionaries(None)
613
settings.remove('spellCheck')
615
def setAllDictionaries(self, dictionary):
616
for hl in self.highlighters:
617
hl.dictionary = dictionary
620
def changeLocale(self):
625
sl, ok = QInputDialog.getText(self, app_name, self.tr('Enter locale name (example: en_US)'), QLineEdit.Normal, text)
630
except Exception as e:
631
QMessageBox.warning(self, app_name, str(e))
634
self.enableSC(self.actionEnableSC.isChecked())
637
self.enableSC(self.actionEnableSC.isChecked())
639
def searchBarVisibilityChanged(self, visible):
640
self.actionSearch.setChecked(visible)
642
self.searchEdit.setFocus(Qt.ShortcutFocusReason)
644
def find(self, back=False):
647
flags = QTextDocument.FindBackward
648
if self.csBox.isChecked():
649
flags = flags | QTextDocument.FindCaseSensitively
650
text = self.searchEdit.text()
651
if not self.findMain(text, flags):
652
if text in self.editBoxes[self.ind].toPlainText():
653
cursor = self.editBoxes[self.ind].textCursor()
655
cursor.movePosition(QTextCursor.End)
657
cursor.movePosition(QTextCursor.Start)
658
self.editBoxes[self.ind].setTextCursor(cursor)
659
self.findMain(text, flags)
661
def findMain(self, text, flags):
663
return self.editBoxes[self.ind].find(text, flags)
665
return self.editBoxes[self.ind].find(text)
667
def getHtml(self, includeStyleSheet=True, includeTitle=True,
668
includeMeta=False, styleForWebKit=False):
669
if self.markups[self.ind] is None:
670
return '<p style="color: red">'\
671
+self.tr('Could not parse file contents, check if you have the necessary module installed!')+'</p>'
672
text = convertToUnicode(self.editBoxes[self.ind].toPlainText())
674
text = text.replace('%HTMLDIR%', 'html')
675
text = text.replace('%\\', '%')
677
if includeStyleSheet:
680
fontname = self.font.family() if self.font else 'Sans'
681
fontsize = (self.font if self.font else QFont()).pointSize()
682
fontline = 'body { font-family: %s; font-size: %spt }\n' % \
684
headers += '<style type="text/css">\n' + fontline + self.ss + '</style>\n'
686
headers += '<meta name="generator" content="%s %s">\n' % \
687
(app_name, app_version)
688
fallbackTitle = self.getDocumentTitle() if includeTitle else ''
689
if includeStyleSheet:
690
return self.markups[self.ind].get_whole_html(text,
691
custom_headers=headers, fallback_title=fallbackTitle)
693
return self.markups[self.ind].get_whole_html(text,
694
custom_headers=headers, include_stylesheet=False,
695
fallback_title=fallbackTitle)
697
def updatePreviewBox(self):
698
self.previewBlocked = False
699
pb = self.previewBoxes[self.ind]
700
textedit = isinstance(pb, QTextEdit)
702
scrollbar = pb.verticalScrollBar()
703
scrollpos = scrollbar.value()
705
frame = pb.page().mainFrame()
706
scrollpos = frame.scrollPosition()
707
if self.actionPlainText.isChecked():
709
pb.setPlainText(self.editBoxes[self.ind].toPlainText())
712
td.setPlainText(self.editBoxes[self.ind].toPlainText())
713
pb.setHtml(td.toHtml())
716
html = self.getHtml(styleForWebKit=(not textedit))
717
except Exception as e:
718
return self.printError(e)
719
if not textedit and '<script ' in html:
720
# Work-around a bug in QtWebKit
721
# by saving the html locally
722
tempFile = QTemporaryFile('retext-XXXXXX.html')
723
tempFile.setAutoRemove(False)
724
tempFile.open(QIODevice.WriteOnly)
725
stream = QTextStream(tempFile)
728
self.connect(pb, SIGNAL('loadFinished(bool)'),
729
lambda ok: tempFile.remove())
730
pb.load(QUrl.fromLocalFile(tempFile.fileName()))
733
if self.font and textedit:
734
pb.document().setDefaultFont(self.font)
736
scrollbar.setValue(scrollpos)
738
frame.setScrollPosition(scrollpos)
740
def updateLivePreviewBox(self):
741
if self.actionLivePreview.isChecked() and self.previewBlocked == False:
742
self.previewBlocked = True
743
QTimer.singleShot(1000, self.updatePreviewBox)
745
def startWpgen(self):
746
if self.fileNames[self.ind] == "":
747
QMessageBox.warning(self, app_name, self.tr("Please, save the file somewhere."))
749
if not (QDir("html").exists() and QFile.exists("template.html")):
750
Popen((wpgen, 'init')).wait()
751
Popen([wpgen, 'updateall']).wait()
752
msgBox = QMessageBox(QMessageBox.Information, app_name,
753
self.tr("Webpages saved in <code>html</code> directory."), QMessageBox.Ok)
754
showButton = msgBox.addButton(self.tr("Show directory"), QMessageBox.AcceptRole)
756
if msgBox.clickedButton() == showButton:
757
QDesktopServices.openUrl(QUrl.fromLocalFile(QDir('html').absolutePath()))
759
QMessageBox.error(self, app_name, self.tr("Webpages generator is not installed!"))
762
if self.fileNames[self.ind]:
763
QDesktopServices.openUrl(QUrl.fromLocalFile(QFileInfo(self.fileNames[self.ind]).path()))
765
QMessageBox.warning(self, app_name, self.tr("Please, save the file somewhere."))
767
def setCurrentFile(self):
768
self.setWindowTitle("")
769
self.tabWidget.setTabText(self.ind, self.getDocumentTitle(baseName=True))
770
self.setWindowFilePath(self.fileNames[self.ind])
771
files = readListFromSettings(settings, "recentFileList")
773
files.prepend(self.fileNames[self.ind])
774
files.removeDuplicates()
777
while self.fileNames[self.ind] in files:
778
files.remove(self.fileNames[self.ind])
779
files.insert(0, self.fileNames[self.ind])
782
writeListToSettings(settings, "recentFileList", files)
783
QDir.setCurrent(QFileInfo(self.fileNames[self.ind]).dir().path())
784
self.docTypeChanged()
787
self.tabWidget.addTab(self.createTab(""), self.tr("New document"))
788
self.ind = self.tabWidget.count()-1
789
self.tabWidget.setCurrentIndex(self.ind)
791
def updateRecentFiles(self):
792
self.menuRecentFiles.clear()
793
self.recentFilesActions = []
794
filesOld = readListFromSettings(settings, "recentFileList")
799
self.recentFilesActions.append(self.act(f, trig=self.openFunction(f)))
800
writeListToSettings(settings, "recentFileList", files)
801
for action in self.recentFilesActions:
802
self.menuRecentFiles.addAction(action)
804
def markupFunction(self, markup):
805
return lambda: self.setDefaultMarkup(markup)
807
def openFunction(self, fileName):
808
return lambda: self.openFileWrapper(fileName)
810
def extensionFuntion(self, data):
812
self.runExtensionCommand(data['Exec'], data['FileFilter'], data['DefaultExtension'])
814
def getExportExtensionsList(self):
816
for extsprefix in ('/usr', QDir.homePath()+'/.local'):
817
extsdir = QDir(extsprefix+'/share/retext/export-extensions/')
819
for fileInfo in extsdir.entryInfoList(['*.desktop', '*.ini'], QDir.Files | QDir.Readable):
820
extensions.append(self.readExtension(fileInfo.filePath()))
821
locale = QLocale.system().name()
822
self.extensionActions = []
823
for extension in extensions:
825
if ('Name[%s]' % locale) in extension:
826
name = extension['Name[%s]' % locale]
827
elif ('Name[%s]' % locale.split('_')[0]) in extension:
828
name = extension['Name[%s]' % locale.split('_')[0]]
830
name = extension['Name']
832
for prop in ('FileFilter', 'DefaultExtension', 'Exec'):
833
if 'X-ReText-'+prop in extension:
834
data[prop] = extension['X-ReText-'+prop]
835
elif prop in extension:
836
data[prop] = extension[prop]
839
action = self.act(name, trig=self.extensionFuntion(data))
840
if 'Icon' in extension:
841
action.setIcon(self.actIcon(extension['Icon']))
842
mimetype = extension['MimeType'] if 'MimeType' in extension else None
844
print('Failed to parse extension: Name is required')
846
self.extensionActions.append((action, mimetype))
848
def updateExtensionsVisibility(self):
849
markupClass = self.getMarkupClass()
850
for action in self.extensionActions:
851
if markupClass is None:
852
action[0].setEnabled(False)
857
elif markupClass == markups.MarkdownMarkup:
858
enabled = (mimetype in ("text/x-retext-markdown", "text/x-markdown"))
859
elif markupClass == markups.ReStructuredTextMarkup:
860
enabled = (mimetype in ("text/x-retext-rst", "text/x-rst"))
863
action[0].setEnabled(enabled)
865
def readExtension(self, fileName):
866
extFile = QFile(fileName)
867
extFile.open(QIODevice.ReadOnly)
869
stream = QTextStream(extFile)
870
while not stream.atEnd():
871
line = convertToUnicode(stream.readLine())
873
index = line.index('=')
874
extension[line[:index].rstrip()] = line[index+1:].lstrip()
879
supportedExtensions = ['.txt']
880
for markup in markups.known_markups:
881
supportedExtensions = supportedExtensions + list(markup.file_extensions)
882
fileFilter = ' (' + str.join(' ', ['*'+ext for ext in supportedExtensions]) + ');;'
883
fileNames = QFileDialog.getOpenFileNames(self, self.tr("Select one or several files to open"), "",
884
self.tr("Supported files") + fileFilter + self.tr("All files (*)"))
885
for fileName in fileNames:
886
self.openFileWrapper(fileName)
888
def openFileWrapper(self, fileName):
891
fileName = QFileInfo(fileName).canonicalFilePath()
893
for i in range(self.tabWidget.count()):
894
if self.fileNames[i] == fileName:
898
self.tabWidget.setCurrentIndex(ex)
899
elif QFile.exists(fileName):
900
if self.fileNames[self.ind] or self.editBoxes[self.ind].toPlainText() \
901
or self.editBoxes[self.ind].document().isModified():
902
self.tabWidget.addTab(self.createTab(""), "")
903
self.ind = self.tabWidget.count()-1
904
self.tabWidget.setCurrentIndex(self.ind)
905
self.fileNames[self.ind] = fileName
908
def openFileMain(self):
909
openfile = QFile(self.fileNames[self.ind])
910
openfile.open(QIODevice.ReadOnly)
911
html = QTextStream(openfile).readAll()
913
self.editBoxes[self.ind].setPlainText(html)
914
suffix = QFileInfo(self.fileNames[self.ind]).suffix()
915
pt = suffix not in ('re', 'md', 'markdown', 'mdown', 'mkd', 'mkdn', 'rst', 'rest')
916
if settings.contains('autoPlainText'):
917
if not readFromSettings(settings, 'autoPlainText', bool):
919
self.actionPlainText.setChecked(pt)
920
self.enablePlainText(pt)
921
self.setCurrentFile()
922
self.setWindowModified(False)
925
self.saveFileMain(dlg=False)
927
def saveFileAs(self):
928
self.saveFileMain(dlg=True)
932
for self.ind in range(self.tabWidget.count()):
933
if self.fileNames[self.ind] and QFileInfo(self.fileNames[self.ind]).isWritable():
934
self.saveFileCore(self.fileNames[self.ind])
935
self.editBoxes[self.ind].document().setModified(False)
938
def saveFileMain(self, dlg):
939
if (not self.fileNames[self.ind]) or dlg:
940
markupClass = self.getMarkupClass()
941
if markupClass is None:
942
defaultExt = self.tr("Plain text (*.txt)")
945
defaultExt = self.tr('%s files') % markupClass.name + ' (' \
946
+ str.join(' ', ['*'+ext for ext in markupClass.file_extensions]) + ')'
947
ext = markupClass.default_extension
948
self.fileNames[self.ind] = QFileDialog.getSaveFileName(self, self.tr("Save file"), "", defaultExt)
949
if self.fileNames[self.ind] and not QFileInfo(self.fileNames[self.ind]).suffix():
950
self.fileNames[self.ind] += ext
951
if self.fileNames[self.ind]:
952
result = self.saveFileCore(self.fileNames[self.ind])
954
self.setCurrentFile()
955
self.editBoxes[self.ind].document().setModified(False)
956
self.setWindowModified(False)
959
QMessageBox.warning(self, app_name, self.tr("Cannot save to file because it is read-only!"))
962
def saveFileCore(self, fn):
964
result = savefile.open(QIODevice.WriteOnly)
966
savestream = QTextStream(savefile)
967
savestream << self.editBoxes[self.ind].toPlainText()
971
def saveHtml(self, fileName):
972
if not QFileInfo(fileName).suffix():
975
htmltext = self.getHtml(includeStyleSheet=False, includeMeta=True)
976
except Exception as e:
977
return self.printError(e)
978
htmlFile = QFile(fileName)
979
htmlFile.open(QIODevice.WriteOnly)
980
html = QTextStream(htmlFile)
984
def textDocument(self):
986
td.setMetaInformation(QTextDocument.DocumentTitle, self.getDocumentTitle())
988
td.setDefaultStyleSheet(self.ss)
989
if self.actionPlainText.isChecked():
990
td.setPlainText(self.editBoxes[self.ind].toPlainText())
992
td.setHtml(self.getHtml())
994
td.setDefaultFont(self.font)
999
document = self.textDocument()
1000
except Exception as e:
1003
fileName = QFileDialog.getSaveFileName(self, self.tr("Export document to ODT"), "", self.tr("OpenDocument text files (*.odt)"))
1004
if not QFileInfo(fileName).suffix():
1006
writer = QTextDocumentWriter(fileName)
1007
writer.setFormat("odf")
1008
writer.write(document)
1010
def saveFilePerfect(self):
1012
fileName = QFileDialog.getSaveFileName(self, self.tr("Save file"), "", self.tr("HTML files (*.html *.htm)"))
1014
self.saveHtml(fileName)
1016
def getDocumentForPrint(self):
1018
return self.previewBoxes[self.ind]
1020
return self.textDocument()
1021
except Exception as e:
1024
def standardPrinter(self):
1025
printer = QPrinter(QPrinter.HighResolution)
1026
printer.setDocName(self.getDocumentTitle())
1027
printer.setCreator(app_name+" "+app_version)
1031
self.updatePreviewBox()
1032
fileName = QFileDialog.getSaveFileName(self, self.tr("Export document to PDF"),
1033
"", self.tr("PDF files (*.pdf)"))
1035
if not QFileInfo(fileName).suffix():
1037
printer = self.standardPrinter()
1038
printer.setOutputFormat(QPrinter.PdfFormat)
1039
printer.setOutputFileName(fileName)
1040
document = self.getDocumentForPrint()
1041
if document != None:
1042
document.print_(printer)
1044
def printFile(self):
1045
self.updatePreviewBox()
1046
printer = self.standardPrinter()
1047
dlg = QPrintDialog(printer, self)
1048
dlg.setWindowTitle(self.tr("Print document"))
1049
if (dlg.exec_() == QDialog.Accepted):
1050
document = self.getDocumentForPrint()
1051
if document != None:
1052
document.print_(printer)
1054
def printPreview(self):
1055
document = self.getDocumentForPrint()
1056
if document == None:
1058
printer = self.standardPrinter()
1059
preview = QPrintPreviewDialog(printer, self)
1060
self.connect(preview, SIGNAL("paintRequested(QPrinter*)"), document.print_)
1063
def runExtensionCommand(self, command, filefilter, defaultext):
1064
of = ('%of' in command)
1065
html = ('%html' in command)
1067
if defaultext and not filefilter:
1068
filefilter = '*'+defaultext
1069
fileName = QFileDialog.getSaveFileName(self, self.tr('Export document'), '', filefilter)
1072
if defaultext and not QFileInfo(fileName).suffix():
1073
fileName += defaultext
1075
tmpname = '.retext-temp.html'
1076
self.saveHtml(tmpname)
1078
tmpname = '.retext-temp' + self.getMarkupClass().default_extension
1079
self.saveFileCore(tmpname)
1080
command = command.replace('%of', 'out'+defaultext)
1081
command = command.replace('%html' if html else '%if', tmpname)
1082
args = str(command).split()
1085
except Exception as error:
1086
errorstr = str(error)
1088
errorstr = QString.fromUtf8(errorstr)
1090
# Not needed for Python 3
1092
QMessageBox.warning(self, app_name, self.tr('Failed to execute the command:') + '\n' + errorstr)
1093
QFile(tmpname).remove()
1095
QFile('out'+defaultext).rename(fileName)
1097
def getDocumentTitle(self, baseName=False):
1098
text = convertToUnicode(self.editBoxes[self.ind].toPlainText())
1099
markup = self.markups[self.ind]
1100
realTitle = markup.get_document_title(text) if markup else ''
1101
if realTitle and not baseName:
1103
elif self.fileNames[self.ind]:
1104
fileinfo = QFileInfo(self.fileNames[self.ind])
1105
basename = fileinfo.completeBaseName()
1106
return (basename if basename else fileinfo.fileName())
1107
return self.tr("New document")
1109
def autoSaveActive(self):
1110
return self.autoSave and self.fileNames[self.ind] and \
1111
QFileInfo(self.fileNames[self.ind]).isWritable()
1113
def modificationChanged(self, changed):
1114
if self.autoSaveActive():
1116
self.actionSave.setEnabled(changed)
1117
self.setWindowModified(changed)
1119
def clipboardDataChanged(self):
1120
self.actionPaste.setEnabled(qApp.clipboard().mimeData().hasText())
1122
def insertChars(self, chars):
1123
tc = self.editBoxes[self.ind].textCursor()
1124
if tc.hasSelection():
1125
selection = convertToUnicode(tc.selectedText())
1126
if selection.startswith(chars) and selection.endswith(chars):
1127
if len(selection) > 2*len(chars):
1128
selection = selection[len(chars):-len(chars)]
1129
tc.insertText(selection)
1131
tc.insertText(chars+tc.selectedText()+chars)
1133
tc.insertText(chars)
1135
def insertTag(self, num):
1137
ut = self.usefulTags[num-1]
1138
arg = ' style=""' if ut == 'span' else ''
1139
tc = self.editBoxes[self.ind].textCursor()
1140
toinsert = '<'+ut+arg+'>'+tc.selectedText()+'</'+ut+'>'
1141
tc.insertText(toinsert)
1142
self.tagsBox.setCurrentIndex(0)
1144
def insertSymbol(self, num):
1146
self.editBoxes[self.ind].insertPlainText('&'+self.usefulChars[num-1]+';')
1147
self.symbolBox.setCurrentIndex(0)
1149
def maybeSave(self, ind):
1150
if self.autoSaveActive():
1151
self.saveFileCore(self.fileNames[self.ind])
1153
if not self.editBoxes[ind].document().isModified():
1155
self.tabWidget.setCurrentIndex(ind)
1156
ret = QMessageBox.warning(self, app_name,
1157
self.tr("The document has been modified.\nDo you want to save your changes?"),
1158
QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel)
1159
if ret == QMessageBox.Save:
1160
return self.saveFileMain(False)
1161
elif ret == QMessageBox.Cancel:
1165
def closeEvent(self, closeevent):
1166
for self.ind in range(self.tabWidget.count()):
1167
if not self.maybeSave(self.ind):
1168
return closeevent.ignore()
1169
if self.restorePreviewState:
1170
if self.livePreviewEnabled:
1171
settings.setValue('previewState', True)
1173
settings.remove('previewState')
1177
HtmlDlg = HtmlDialog(self)
1179
htmltext = self.getHtml(includeStyleSheet=False, includeTitle=False)
1180
except Exception as e:
1181
return self.printError(e)
1182
winTitle = self.getDocumentTitle(baseName=True)
1184
HtmlDlg.setWindowTitle(winTitle+" ("+self.tr("HTML code")+") "+QChar(0x2014)+" "+app_name)
1187
HtmlDlg.setWindowTitle(winTitle+" ("+self.tr("HTML code")+") \u2014 "+app_name)
1188
HtmlDlg.textEdit.setPlainText(htmltext)
1191
HtmlDlg.activateWindow()
1194
QDesktopServices.openUrl(QUrl('http://sourceforge.net/p/retext/home/Help and Support'))
1196
def aboutDialog(self):
1197
QMessageBox.about(self, self.aboutWindowTitle,
1198
'<p><b>'+app_name+' '+app_version+'</b><br>'+self.tr('Simple but powerful editor for Markdown and ReStructuredText')
1199
+'</p><p>'+self.tr('Author: Dmitry Shachnev, 2011')
1200
+'<br><a href="http://sourceforge.net/p/retext/">'+self.tr('Website')
1201
+'</a> | <a href="http://daringfireball.net/projects/markdown/syntax">'+self.tr('Markdown syntax')
1202
+'</a> | <a href="http://docutils.sourceforge.net/docs/user/rst/quickref.html">'
1203
+self.tr('ReST syntax')+'</a></p>')
1205
def enablePlainText(self, value):
1206
self.aptc[self.ind] = value
1207
self.actionPerfectHtml.setDisabled(value)
1208
self.actionViewHtml.setDisabled(value)
1209
self.updatePreviewBox()
1210
self.docTypeChanged()
1212
def setDefaultMarkup(self, markup):
1213
self.defaultMarkup = markup
1214
settings.setValue('defaultMarkup', markup.name)
1216
for self.ind in range(len(self.previewBoxes)):
1217
self.docTypeChanged()