~ubuntu-branches/ubuntu/raring/retext/raring

« back to all changes in this revision

Viewing changes to .pc/git_fix_insert_chars.patch/retext.py

  • Committer: Package Import Robot
  • Author(s): Dmitry Shachnev
  • Date: 2012-05-25 13:20:54 UTC
  • mfrom: (1.1.9) (8.1.4 sid)
  • Revision ID: package-import@ubuntu.com-20120525132054-xuk4x01a8xlik0fi
Tags: 3.0.4-1
* New upstream release
  - "Quit" menu action now works correctly
  - Fixed crash when trying to save files to a read-only directory
  - If Qt doesn't know icon theme name, try to load it from gconf
  - Added German translation
* Updated translations from Transifex
* Drop git_fix_insert_chars.patch, it's in the new release

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#!/usr/bin/env python
2
 
# -*- coding: utf-8 -*-
3
 
# vim: sw=8:ts=8:noexpandtab
4
 
 
5
 
# ReText
6
 
# Copyright 2011-2012 Dmitry Shachnev
7
 
 
8
 
# This program is free software; you can redistribute it and/or modify
9
 
# it under the terms of the GNU General Public License as published by
10
 
# the Free Software Foundation; either version 2 of the License, or
11
 
# (at your option) any later version.
12
 
 
13
 
# This program is distributed in the hope that it will be useful,
14
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 
# GNU General Public License for more details.
17
 
 
18
 
# You should have received a copy of the GNU General Public License
19
 
# along with this program; if not, write to the Free Software
20
 
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21
 
# MA 02110-1301, USA.
22
 
 
23
 
import sys
24
 
import re
25
 
from subprocess import Popen
26
 
from PyQt4.QtCore import *
27
 
from PyQt4.QtGui import *
28
 
 
29
 
app_name = "ReText"
30
 
app_version = "3.0.3"
31
 
 
32
 
def readFromSettings(settings, key, keytype):
33
 
        try:
34
 
                return settings.value(key, type=keytype)
35
 
        except TypeError:
36
 
                # For old PyQt versions
37
 
                if keytype == str:
38
 
                        return settings.value(key).toString()
39
 
                elif keytype == int:
40
 
                        result, ok = settings.value(key).toInt()
41
 
                        if not ok:
42
 
                                print('Warning: cannot covert settings value to int!')
43
 
                        return result
44
 
                elif keytype == bool:
45
 
                        return settings.value(key).toBool()
46
 
 
47
 
def readListFromSettings(settings, key):
48
 
        if not settings.contains(key):
49
 
                return []
50
 
        value = settings.value(key)
51
 
        try:
52
 
                return value.toStringList()
53
 
        except:
54
 
                # For Python 3
55
 
                if isinstance(value, str):
56
 
                        return [value]
57
 
                else:
58
 
                        return value
59
 
 
60
 
def writeListToSettings(settings, key, value):
61
 
        if len(value) > 1:
62
 
                settings.setValue(key, value)
63
 
        elif len(value) == 1:
64
 
                settings.setValue(key, value[0])
65
 
        else:
66
 
                settings.remove(key)
67
 
 
68
 
settings = QSettings('ReText project', 'ReText')
69
 
 
70
 
try:
71
 
        import markdown
72
 
except:
73
 
        use_md = False
74
 
else:
75
 
        use_md = True
76
 
        exts = []
77
 
        if settings.contains('mdExtensions'):
78
 
                for ext in readListFromSettings(settings, 'mdExtensions'):
79
 
                        exts.append(str(ext))
80
 
                md = markdown.Markdown(exts)
81
 
        else:
82
 
                md = markdown.Markdown()
83
 
 
84
 
try:
85
 
        import gdata.docs.data
86
 
        import gdata.docs.client
87
 
        from gdata.data import MediaSource
88
 
except:
89
 
        use_gdocs = False
90
 
else:
91
 
        use_gdocs = True
92
 
 
93
 
try:
94
 
        import enchant
95
 
        enchant.Dict()
96
 
except:
97
 
        use_enchant = False
98
 
else:
99
 
        use_enchant = True
100
 
 
101
 
dictionary = None
102
 
 
103
 
try:
104
 
        from docutils.core import publish_parts
105
 
except:
106
 
        use_docutils = False
107
 
else:
108
 
        use_docutils = True
109
 
 
110
 
icon_path = "icons/"
111
 
 
112
 
PARSER_DOCUTILS, PARSER_MARKDOWN, PARSER_HTML, PARSER_NA = range(4)
113
 
 
114
 
if QFileInfo("wpgen/wpgen.py").isExecutable():
115
 
        try:
116
 
                wpgen = unicode(QFileInfo("wpgen/wpgen.py").canonicalFilePath(), 'utf-8')
117
 
        except:
118
 
                # For Python 3
119
 
                wpgen = QFileInfo("wpgen/wpgen.py").canonicalFilePath()
120
 
elif QFileInfo("/usr/bin/wpgen").isExecutable():
121
 
        wpgen = "/usr/bin/wpgen"
122
 
else:
123
 
        wpgen = None
124
 
 
125
 
monofont = QFont()
126
 
if settings.contains('editorFont'):
127
 
        monofont.setFamily(readFromSettings(settings, 'editorFont', str))
128
 
else:
129
 
        monofont.setFamily('monospace')
130
 
if settings.contains('editorFontSize'):
131
 
        monofont.setPointSize(readFromSettings(settings, 'editorFontSize', int))
132
 
 
133
 
try:
134
 
        from PyQt4.QtWebKit import QWebView, QWebSettings
135
 
except:
136
 
        webkit_available = False
137
 
else:
138
 
        webkit_available = True
139
 
 
140
 
class ReTextHighlighter(QSyntaxHighlighter):
141
 
        def highlightBlock(self, text):
142
 
                patterns = (
143
 
                        ('<[^<>]*>', Qt.darkMagenta, QFont.Bold),          # HTML tags
144
 
                        ('&[^; ]*;', Qt.darkCyan, QFont.Bold),             # HTML symbols
145
 
                        ('"[^"<]*"(?=[^<]*>)', Qt.darkYellow, QFont.Bold), # Quoted strings inside tags
146
 
                        ('<!--[^<>]*-->', Qt.gray, QFont.Normal),          # HTML comments
147
 
                        ('(?<!\\*)\\*[^ \\*][^\\*]*\\*', None, QFont.Normal, True), # *Italics*
148
 
                        ('(?<!_|\\w)_[^_]+_(?!\\w)', None, QFont.Normal, True),     # _Italics_
149
 
                        ('(?<!\\*)\\*\\*((?!\\*\\*).)*\\*\\*', None, QFont.Bold), # **Bold**
150
 
                        ('(?<!_|\\w)__[^_]+__(?!\\w)', None, QFont.Bold),         # __Bold__
151
 
                        ('\\*{3,3}[^\\*]+\\*{3,3}', None, QFont.Bold, True), # ***BoldItalics***
152
 
                        ('___[^_]+___', None, QFont.Bold, True),           # ___BoldItalics___
153
 
                        ('^#.+', None, QFont.Black),                       # Headers
154
 
                        ('(?<=\\[)[^\\[\\]]*(?=\\])', Qt.blue, QFont.Normal), # Links and images
155
 
                        ('(?<=\\]\\()[^\\(\\)]*(?=\\))', None, QFont.Normal, True, True) # Link references
156
 
                )
157
 
                for pattern in patterns:
158
 
                        charFormat = QTextCharFormat()
159
 
                        charFormat.setFontWeight(pattern[2])
160
 
                        if pattern[1] != None:
161
 
                                charFormat.setForeground(pattern[1])
162
 
                        if len(pattern) >= 4:
163
 
                                charFormat.setFontItalic(pattern[3])
164
 
                        if len(pattern) >= 5:
165
 
                                charFormat.setFontUnderline(pattern[4])
166
 
                        for match in re.finditer(pattern[0], text):
167
 
                                self.setFormat(match.start(), match.end() - match.start(), charFormat)
168
 
                if dictionary:
169
 
                        try:
170
 
                                text = unicode(text)
171
 
                        except:
172
 
                                # Not necessary for Python 3
173
 
                                pass
174
 
                        charFormat = QTextCharFormat()
175
 
                        charFormat.setUnderlineColor(Qt.red)
176
 
                        charFormat.setUnderlineStyle(QTextCharFormat.SpellCheckUnderline)
177
 
                        for match in re.finditer('[^_\\W]+', text, flags=re.UNICODE):
178
 
                                finalFormat = QTextCharFormat()
179
 
                                finalFormat.merge(charFormat)
180
 
                                finalFormat.merge(self.format(match.start()))
181
 
                                if not dictionary.check(match.group(0)):
182
 
                                        self.setFormat(match.start(), match.end() - match.start(), finalFormat)
183
 
 
184
 
class LogPassDialog(QDialog):
185
 
        def __init__(self, defaultLogin="", defaultPass=""):
186
 
                QDialog.__init__(self)
187
 
                self.setWindowTitle(app_name)
188
 
                self.verticalLayout = QVBoxLayout(self)
189
 
                self.label = QLabel(self)
190
 
                self.label.setText(self.tr("Enter your Google account data"))
191
 
                self.verticalLayout.addWidget(self.label)
192
 
                self.loginEdit = QLineEdit(self)
193
 
                self.loginEdit.setText(defaultLogin)
194
 
                self.verticalLayout.addWidget(self.loginEdit)
195
 
                self.passEdit = QLineEdit(self)
196
 
                self.passEdit.setText(defaultPass)
197
 
                self.passEdit.setEchoMode(QLineEdit.Password)
198
 
                try:
199
 
                        self.loginEdit.setPlaceholderText(self.tr("Username"))
200
 
                        self.passEdit.setPlaceholderText(self.tr("Password"))
201
 
                except:
202
 
                        pass
203
 
                self.verticalLayout.addWidget(self.passEdit)
204
 
                self.buttonBox = QDialogButtonBox(self)
205
 
                self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok)
206
 
                self.verticalLayout.addWidget(self.buttonBox)
207
 
                self.connect(self.buttonBox, SIGNAL("accepted()"), self.accept)
208
 
                self.connect(self.buttonBox, SIGNAL("rejected()"), self.reject)
209
 
 
210
 
class HtmlDialog(QDialog):
211
 
        def __init__(self, parent=None):
212
 
                QDialog.__init__(self, parent)
213
 
                self.resize(600, 500)
214
 
                self.verticalLayout = QVBoxLayout(self)
215
 
                self.textEdit = QTextEdit(self)
216
 
                self.textEdit.setReadOnly(True)
217
 
                self.textEdit.setFont(monofont)
218
 
                ReTextHighlighter(self.textEdit.document())
219
 
                self.verticalLayout.addWidget(self.textEdit)
220
 
                self.buttonBox = QDialogButtonBox(self)
221
 
                self.buttonBox.setStandardButtons(QDialogButtonBox.Close)
222
 
                self.connect(self.buttonBox, SIGNAL("clicked(QAbstractButton*)"), self.doClose)
223
 
                self.verticalLayout.addWidget(self.buttonBox)
224
 
        
225
 
        def doClose(self):
226
 
                self.close()
227
 
 
228
 
class ReTextWindow(QMainWindow):
229
 
        def __init__(self, parent=None):
230
 
                QMainWindow.__init__(self, parent)
231
 
                self.resize(800, 600)
232
 
                screen = QDesktopWidget().screenGeometry()
233
 
                size = self.geometry()
234
 
                self.move((screen.width()-size.width())/2, (screen.height()-size.height())/2)
235
 
                if settings.contains('iconTheme'):
236
 
                        QIcon.setThemeName(readFromSettings(settings, 'iconTheme', str))
237
 
                if settings.contains('font'):
238
 
                        self.font = QFont(readFromSettings(settings, 'font', str))
239
 
                        if settings.contains('fontSize'):
240
 
                                self.font.setPointSize(readFromSettings(settings, 'fontSize', int))
241
 
                else:
242
 
                        self.font = None
243
 
                if QFile.exists(icon_path+'retext.png'):
244
 
                        self.setWindowIcon(QIcon(icon_path+'retext.png'))
245
 
                else:
246
 
                        self.setWindowIcon(QIcon.fromTheme('retext', QIcon.fromTheme('accessories-text-editor')))
247
 
                self.editBoxes = []
248
 
                self.previewBoxes = []
249
 
                self.highlighters = []
250
 
                self.fileNames = []
251
 
                self.apc = []
252
 
                self.alpc = []
253
 
                self.aptc = []
254
 
                self.gDocsEntries = []
255
 
                self.tabWidget = QTabWidget(self)
256
 
                self.tabWidget.setTabsClosable(True)
257
 
                self.setCentralWidget(self.tabWidget)
258
 
                self.connect(self.tabWidget, SIGNAL('currentChanged(int)'), self.changeIndex)
259
 
                self.connect(self.tabWidget, SIGNAL('tabCloseRequested(int)'), self.closeTab)
260
 
                self.toolBar = QToolBar(self.tr('File toolbar'), self)
261
 
                self.addToolBar(Qt.TopToolBarArea, self.toolBar)
262
 
                self.editBar = QToolBar(self.tr('Edit toolbar'), self)
263
 
                self.addToolBar(Qt.TopToolBarArea, self.editBar)
264
 
                self.searchBar = QToolBar(self.tr('Search toolbar'), self)
265
 
                self.addToolBar(Qt.BottomToolBarArea, self.searchBar)
266
 
                self.actionNew = self.act(self.tr('New'), icon='document-new', shct=QKeySequence.New, trig=self.createNew)
267
 
                self.actionNew.setPriority(QAction.LowPriority)
268
 
                self.actionOpen = self.act(self.tr('Open'), icon='document-open', shct=QKeySequence.Open, trig=self.openFile)
269
 
                self.actionOpen.setPriority(QAction.LowPriority)
270
 
                self.actionSave = self.act(self.tr('Save'), icon='document-save', shct=QKeySequence.Save, trig=self.saveFile)
271
 
                self.actionSave.setEnabled(False)
272
 
                self.actionSave.setPriority(QAction.LowPriority)
273
 
                self.actionSaveAs = self.act(self.tr('Save as'), icon='document-save-as', shct=QKeySequence.SaveAs, \
274
 
                trig=self.saveFileAs)
275
 
                self.actionPrint = self.act(self.tr('Print'), icon='document-print', shct=QKeySequence.Print, trig=self.printFile)
276
 
                self.actionPrint.setPriority(QAction.LowPriority)
277
 
                self.actionPrintPreview = self.act(self.tr('Print preview'), icon='document-print-preview', \
278
 
                trig=self.printPreview)
279
 
                self.actionViewHtml = self.act(self.tr('View HTML code'), icon='text-html', trig=self.viewHtml)
280
 
                self.actionChangeFont = self.act(self.tr('Change default font'), trig=self.changeFont)
281
 
                self.actionSearch = self.act(self.tr('Find text'), icon='edit-find', shct=QKeySequence.Find)
282
 
                self.actionSearch.setCheckable(True)
283
 
                self.connect(self.actionSearch, SIGNAL('triggered(bool)'), self.searchBar, SLOT('setVisible(bool)'))
284
 
                self.connect(self.searchBar, SIGNAL('visibilityChanged(bool)'), self.searchBarVisibilityChanged)
285
 
                self.actionPreview = self.act(self.tr('Preview'), shct=Qt.CTRL+Qt.Key_E, trigbool=self.preview)
286
 
                if QIcon.hasThemeIcon('document-preview'):
287
 
                        self.actionPreview.setIcon(QIcon.fromTheme('document-preview'))
288
 
                elif QIcon.hasThemeIcon('preview-file'):
289
 
                        self.actionPreview.setIcon(QIcon.fromTheme('preview-file'))
290
 
                elif QIcon.hasThemeIcon('x-office-document'):
291
 
                        self.actionPreview.setIcon(QIcon.fromTheme('x-office-document'))
292
 
                else:
293
 
                        self.actionPreview.setIcon(QIcon(icon_path+'document-preview.png'))
294
 
                self.actionLivePreview = self.act(self.tr('Live preview'), shct=Qt.CTRL+Qt.SHIFT+Qt.Key_E, \
295
 
                trigbool=self.enableLivePreview)
296
 
                self.actionFullScreen = self.act(self.tr('Fullscreen mode'), icon='view-fullscreen', shct=Qt.Key_F11, \
297
 
                trigbool=self.enableFullScreen)
298
 
                self.actionPerfectHtml = self.act('HTML', icon='text-html', trig=self.saveFilePerfect)
299
 
                self.actionPdf = self.act('PDF', icon='application-pdf', trig=self.savePdf)
300
 
                self.actionOdf = self.act('ODT', icon='x-office-document', trig=self.saveOdf)
301
 
                settings.beginGroup('Export')
302
 
                if settings.allKeys():
303
 
                        self.actionOtherExport = self.act(self.tr('Other formats'), trig=self.otherExport)
304
 
                        otherExport = True
305
 
                else:
306
 
                        otherExport = False
307
 
                settings.endGroup()
308
 
                self.getExportExtensionsList()
309
 
                self.actionQuit = self.act(self.tr('Quit'), icon='application-exit', shct=QKeySequence.Quit)
310
 
                self.actionQuit.setMenuRole(QAction.QuitRole)
311
 
                self.connect(self.actionQuit, SIGNAL('triggered()'), qApp, SLOT('quit()'))
312
 
                self.actionUndo = self.act(self.tr('Undo'), icon='edit-undo', shct=QKeySequence.Undo, \
313
 
                trig=lambda: self.editBoxes[self.ind].undo())
314
 
                self.actionRedo = self.act(self.tr('Redo'), icon='edit-redo', shct=QKeySequence.Redo, \
315
 
                trig=lambda: self.editBoxes[self.ind].redo())
316
 
                self.actionCopy = self.act(self.tr('Copy'), icon='edit-copy', shct=QKeySequence.Copy, \
317
 
                trig=lambda: self.editBoxes[self.ind].copy())
318
 
                self.actionCut = self.act(self.tr('Cut'), icon='edit-cut', shct=QKeySequence.Cut, \
319
 
                trig=lambda: self.editBoxes[self.ind].cut())
320
 
                self.actionPaste = self.act(self.tr('Paste'), icon='edit-paste', shct=QKeySequence.Paste, \
321
 
                trig=lambda: self.editBoxes[self.ind].paste())
322
 
                self.actionUndo.setEnabled(False)
323
 
                self.actionRedo.setEnabled(False)
324
 
                self.actionCopy.setEnabled(False)
325
 
                self.actionCut.setEnabled(False)
326
 
                self.connect(qApp.clipboard(), SIGNAL('dataChanged()'), self.clipboardDataChanged)
327
 
                self.clipboardDataChanged()
328
 
                self.sc = False
329
 
                if use_enchant:
330
 
                        self.actionEnableSC = self.act(self.tr('Enable'), trigbool=self.enableSC)
331
 
                        self.actionSetLocale = self.act(self.tr('Set locale'), trig=self.changeLocale)
332
 
                        if settings.contains('spellCheckLocale'):
333
 
                                self.sl = str(readFromSettings(settings, 'spellCheckLocale', str))
334
 
                        else:
335
 
                                self.sl = None
336
 
                        if settings.contains('spellCheck'):
337
 
                                if readFromSettings(settings, 'spellCheck', bool):
338
 
                                        self.actionEnableSC.setChecked(True)
339
 
                                        self.enableSC(True)
340
 
                self.actionPlainText = self.act(self.tr('Plain text'), trigbool=self.enablePlainText)
341
 
                if webkit_available:
342
 
                        self.actionWebKit = self.act(self.tr('Use WebKit renderer'), trigbool=self.enableWebKit)
343
 
                        self.useWebKit = False
344
 
                        if settings.contains('useWebKit'):
345
 
                                if readFromSettings(settings, 'useWebKit', bool):
346
 
                                        self.useWebKit = True
347
 
                                        self.actionWebKit.setChecked(True)
348
 
                if wpgen:
349
 
                        self.actionWpgen = self.act(self.tr('Generate webpages'), trig=self.startWpgen)
350
 
                self.actionShow = self.act(self.tr('Show'), icon='system-file-manager', trig=self.showInDir)
351
 
                self.actionFind = self.act(self.tr('Next'), icon='go-next', shct=QKeySequence.FindNext, trig=self.find)
352
 
                self.actionFindPrev = self.act(self.tr('Previous'), icon='go-previous', shct=QKeySequence.FindPrevious, \
353
 
                trig=lambda: self.find(back=True))
354
 
                self.actionHelp = self.act(self.tr('Get help online'), icon='help-contents', trig=self.openHelp)
355
 
                try:
356
 
                        self.aboutWindowTitle = self.tr('About %s') % app_name
357
 
                except:
358
 
                        # For Python 2
359
 
                        self.aboutWindowTitle = self.tr('About %s').replace('%s', '%1').arg(app_name)
360
 
                self.actionAbout = self.act(self.aboutWindowTitle, icon='help-about', trig=self.aboutDialog)
361
 
                self.actionAbout.setMenuRole(QAction.AboutRole)
362
 
                self.actionAboutQt = self.act(self.tr('About Qt'))
363
 
                self.actionAboutQt.setMenuRole(QAction.AboutQtRole)
364
 
                self.connect(self.actionAboutQt, SIGNAL('triggered()'), qApp, SLOT('aboutQt()'))
365
 
                self.chooseGroup = QActionGroup(self)
366
 
                self.useDocUtils = False
367
 
                self.actionUseMarkdown = self.act('Markdown')
368
 
                self.actionUseMarkdown.setCheckable(True)
369
 
                self.actionUseReST = self.act('ReStructuredText')
370
 
                self.actionUseReST.setCheckable(True)
371
 
                if settings.contains('useReST'):
372
 
                        if readFromSettings(settings, 'useReST', bool):
373
 
                                if use_docutils:
374
 
                                        self.useDocUtils = True
375
 
                                self.actionUseReST.setChecked(True)
376
 
                        else:
377
 
                                self.actionUseMarkdown.setChecked(True)
378
 
                else:
379
 
                        self.actionUseMarkdown.setChecked(True)
380
 
                self.connect(self.actionUseReST, SIGNAL('toggled(bool)'), self.setDocUtilsDefault)
381
 
                self.chooseGroup.addAction(self.actionUseMarkdown)
382
 
                self.chooseGroup.addAction(self.actionUseReST)
383
 
                self.actionBold = self.act(self.tr('Bold'), shct=QKeySequence.Bold, trig=lambda: self.insertChars('**'))
384
 
                self.actionItalic = self.act(self.tr('Italic'), shct=QKeySequence.Italic, trig=lambda: self.insertChars('*'))
385
 
                self.actionUnderline = self.act(self.tr('Underline'), shct=QKeySequence.Underline, \
386
 
                trig=lambda: self.insertTag(9)) # <u>...</u>
387
 
                if use_gdocs:
388
 
                        self.actionSaveGDocs = self.act(self.tr('Save to Google Docs'), trig=self.saveGDocs)
389
 
                        self.actionSaveGDocs.setIcon(QIcon.fromTheme('web-browser', self.actIcon('intenret-web-browser')))
390
 
                self.usefulTags = ('big', 'center', 's', 'small', 'span', 'table', 'td', 'tr', 'u')
391
 
                self.usefulChars = ('deg', 'divide', 'hellip', 'laquo', 'larr', \
392
 
                        'lsquo', 'mdash', 'middot', 'minus', 'nbsp', 'ndash', 'raquo', \
393
 
                        'rarr', 'rsquo', 'times')
394
 
                self.tagsBox = QComboBox(self.editBar)
395
 
                self.tagsBox.addItem(self.tr('Tags'))
396
 
                self.tagsBox.addItems(self.usefulTags)
397
 
                self.connect(self.tagsBox, SIGNAL('activated(int)'), self.insertTag)
398
 
                self.symbolBox = QComboBox(self.editBar)
399
 
                self.symbolBox.addItem(self.tr('Symbols'))
400
 
                self.symbolBox.addItems(self.usefulChars)
401
 
                self.connect(self.symbolBox, SIGNAL('activated(int)'), self.insertSymbol)
402
 
                if settings.contains('styleSheet'):
403
 
                        ssname = readFromSettings(settings, 'styleSheet', str)
404
 
                        sheetfile = QFile(ssname)
405
 
                        sheetfile.open(QIODevice.ReadOnly)
406
 
                        self.ss = QTextStream(sheetfile).readAll()
407
 
                        sheetfile.close()
408
 
                        webkitsettings = QWebSettings.globalSettings()
409
 
                        webkitsettings.setUserStyleSheetUrl(QUrl.fromLocalFile(ssname))
410
 
                else:
411
 
                        self.ss = ''
412
 
                if use_md and 'codehilite' in exts:
413
 
                        # Load CSS style for codehilite
414
 
                        try:
415
 
                                from pygments.formatters import HtmlFormatter
416
 
                        except:
417
 
                                pass
418
 
                        else:
419
 
                                self.ss += HtmlFormatter().get_style_defs('.codehilite')
420
 
                self.menubar = QMenuBar(self)
421
 
                self.menubar.setGeometry(QRect(0, 0, 800, 25))
422
 
                self.setMenuBar(self.menubar)
423
 
                self.menuFile = self.menubar.addMenu(self.tr('File'))
424
 
                self.menuEdit = self.menubar.addMenu(self.tr('Edit'))
425
 
                self.menuHelp = self.menubar.addMenu(self.tr('Help'))
426
 
                self.menuFile.addAction(self.actionNew)
427
 
                self.menuFile.addAction(self.actionOpen)
428
 
                self.menuRecentFiles = self.menuFile.addMenu(self.tr('Open recent'))
429
 
                self.connect(self.menuRecentFiles, SIGNAL('aboutToShow()'), self.updateRecentFiles)
430
 
                self.menuFile.addMenu(self.menuRecentFiles)
431
 
                self.menuDir = self.menuFile.addMenu(self.tr('Directory'))
432
 
                self.menuDir.addAction(self.actionShow)
433
 
                if wpgen:
434
 
                        self.menuDir.addAction(self.actionWpgen)
435
 
                self.menuFile.addSeparator()
436
 
                self.menuFile.addAction(self.actionSave)
437
 
                self.menuFile.addAction(self.actionSaveAs)
438
 
                self.menuFile.addSeparator()
439
 
                self.menuExport = self.menuFile.addMenu(self.tr('Export'))
440
 
                self.menuExport.addAction(self.actionPerfectHtml)
441
 
                self.menuExport.addAction(self.actionOdf)
442
 
                self.menuExport.addAction(self.actionPdf)
443
 
                if self.extensionActions:
444
 
                        self.menuExport.addSeparator()
445
 
                        for action, mimetype in self.extensionActions:
446
 
                                self.menuExport.addAction(action)
447
 
                        self.connect(self.menuRecentFiles, SIGNAL('aboutToShow()'), self.updateExtensionsVisibility)
448
 
                if otherExport:
449
 
                        self.menuExport.addAction(self.actionOtherExport)
450
 
                if use_gdocs:
451
 
                        self.menuExport.addSeparator()
452
 
                        self.menuExport.addAction(self.actionSaveGDocs)
453
 
                self.menuFile.addAction(self.actionPrint)
454
 
                self.menuFile.addAction(self.actionPrintPreview)
455
 
                self.menuFile.addSeparator()
456
 
                self.menuFile.addAction(self.actionQuit)
457
 
                self.menuEdit.addAction(self.actionUndo)
458
 
                self.menuEdit.addAction(self.actionRedo)
459
 
                self.menuEdit.addSeparator()
460
 
                self.menuEdit.addAction(self.actionCut)
461
 
                self.menuEdit.addAction(self.actionCopy)
462
 
                self.menuEdit.addAction(self.actionPaste)
463
 
                self.menuEdit.addSeparator()
464
 
                if use_enchant:
465
 
                        self.menuSC = self.menuEdit.addMenu(self.tr('Spell check'))
466
 
                        self.menuSC.addAction(self.actionEnableSC)
467
 
                        self.menuSC.addAction(self.actionSetLocale)
468
 
                self.menuEdit.addAction(self.actionSearch)
469
 
                self.menuEdit.addAction(self.actionPlainText)
470
 
                self.menuEdit.addAction(self.actionChangeFont)
471
 
                self.menuEdit.addSeparator()
472
 
                if use_docutils and use_md:
473
 
                        self.menuMode = self.menuEdit.addMenu(self.tr('Default editing mode'))
474
 
                        self.menuMode.addAction(self.actionUseMarkdown)
475
 
                        self.menuMode.addAction(self.actionUseReST)
476
 
                self.menuFormat = self.menuEdit.addMenu(self.tr('Formatting'))
477
 
                self.menuFormat.addAction(self.actionBold)
478
 
                self.menuFormat.addAction(self.actionItalic)
479
 
                self.menuFormat.addAction(self.actionUnderline)
480
 
                if webkit_available:
481
 
                        self.menuEdit.addAction(self.actionWebKit)
482
 
                self.menuEdit.addSeparator()
483
 
                self.menuEdit.addAction(self.actionViewHtml)
484
 
                self.menuEdit.addAction(self.actionLivePreview)
485
 
                self.menuEdit.addAction(self.actionPreview)
486
 
                self.menuEdit.addSeparator()
487
 
                self.menuEdit.addAction(self.actionFullScreen)
488
 
                self.menuHelp.addAction(self.actionHelp)
489
 
                self.menuHelp.addSeparator()
490
 
                self.menuHelp.addAction(self.actionAbout)
491
 
                self.menuHelp.addAction(self.actionAboutQt)
492
 
                self.menubar.addMenu(self.menuFile)
493
 
                self.menubar.addMenu(self.menuEdit)
494
 
                self.menubar.addMenu(self.menuHelp)
495
 
                self.toolBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
496
 
                self.toolBar.addAction(self.actionNew)
497
 
                self.toolBar.addSeparator()
498
 
                self.toolBar.addAction(self.actionOpen)
499
 
                self.toolBar.addAction(self.actionSave)
500
 
                self.toolBar.addAction(self.actionPrint)
501
 
                self.toolBar.addSeparator()
502
 
                self.toolBar.addAction(self.actionPreview)
503
 
                self.editBar.addAction(self.actionUndo)
504
 
                self.editBar.addAction(self.actionRedo)
505
 
                self.editBar.addSeparator()
506
 
                self.editBar.addAction(self.actionCut)
507
 
                self.editBar.addAction(self.actionCopy)
508
 
                self.editBar.addAction(self.actionPaste)
509
 
                self.editBar.addSeparator()
510
 
                self.editBar.addWidget(self.tagsBox)
511
 
                self.editBar.addWidget(self.symbolBox)
512
 
                self.searchEdit = QLineEdit(self.searchBar)
513
 
                try:
514
 
                        self.searchEdit.setPlaceholderText(self.tr('Search'))
515
 
                except:
516
 
                        pass
517
 
                self.connect(self.searchEdit, SIGNAL('returnPressed()'), self.find)
518
 
                self.csBox = QCheckBox(self.tr('Case sensitively'), self.searchBar)
519
 
                self.searchBar.addWidget(self.searchEdit)
520
 
                self.searchBar.addWidget(self.csBox)
521
 
                self.searchBar.addAction(self.actionFindPrev)
522
 
                self.searchBar.addAction(self.actionFind)
523
 
                self.searchBar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
524
 
                self.searchBar.setVisible(False)
525
 
                self.autoSave = False
526
 
                if settings.contains('autoSave'):
527
 
                        if readFromSettings(settings, 'autoSave', bool):
528
 
                                self.autoSave = True
529
 
                                timer = QTimer(self)
530
 
                                timer.start(60000)
531
 
                                self.connect(timer, SIGNAL('timeout()'), self.saveAll)
532
 
                self.restorePreviewState = False
533
 
                self.livePreviewEnabled = False
534
 
                if settings.contains('restorePreviewState'):
535
 
                        self.restorePreviewState = readFromSettings(settings, 'restorePreviewState', bool)
536
 
                if settings.contains('previewState'):
537
 
                        self.livePreviewEnabled = readFromSettings(settings, 'previewState', bool)
538
 
                self.ind = 0
539
 
                self.tabWidget.addTab(self.createTab(""), self.tr('New document'))
540
 
                if not (use_md or use_docutils):
541
 
                        QMessageBox.warning(self, app_name, self.tr('You have neither Markdown nor Docutils modules installed!') \
542
 
                        +'<br>'+self.tr('Only HTML formatting will be available.'))
543
 
        
544
 
        def act(self, name, icon=None, trig=None, trigbool=None, shct=None):
545
 
                if icon:
546
 
                        action = QAction(self.actIcon(icon), name, self)
547
 
                else:
548
 
                        action = QAction(name, self)
549
 
                if trig:
550
 
                        self.connect(action, SIGNAL('triggered()'), trig)
551
 
                elif trigbool:
552
 
                        action.setCheckable(True)
553
 
                        self.connect(action, SIGNAL('triggered(bool)'), trigbool)
554
 
                if shct:
555
 
                        action.setShortcut(shct)
556
 
                return action
557
 
        
558
 
        def actIcon(self, name):
559
 
                return QIcon.fromTheme(name, QIcon(icon_path+name+'.png'))
560
 
        
561
 
        def printError(self, error):
562
 
                print('Exception occured while parsing document:')
563
 
                print(error)
564
 
        
565
 
        def getSplitter(self, index):
566
 
                splitter = QSplitter(Qt.Horizontal)
567
 
                # Give both boxes a minimum size so the minimumSizeHint will be
568
 
                # ignored when splitter.setSizes is called below
569
 
                for widget in self.editBoxes[index], self.previewBoxes[index]:
570
 
                        widget.setMinimumWidth(125)
571
 
                        splitter.addWidget(widget)
572
 
                splitter.setSizes((50, 50))
573
 
                splitter.setChildrenCollapsible(False)
574
 
                return splitter
575
 
        
576
 
        def createTab(self, fileName):
577
 
                self.previewBlocked = False
578
 
                self.editBoxes.append(QTextEdit())
579
 
                self.highlighters.append(ReTextHighlighter(self.editBoxes[-1].document()))
580
 
                if self.useWebKit:
581
 
                        self.previewBoxes.append(QWebView())
582
 
                else:
583
 
                        self.previewBoxes.append(QTextEdit())
584
 
                        self.previewBoxes[-1].setReadOnly(True)
585
 
                self.previewBoxes[-1].setVisible(False)
586
 
                self.fileNames.append(fileName)
587
 
                liveMode = self.restorePreviewState and self.livePreviewEnabled
588
 
                self.apc.append(liveMode)
589
 
                self.alpc.append(liveMode)
590
 
                self.aptc.append(False)
591
 
                self.gDocsEntries.append(None)
592
 
                self.editBoxes[-1].setFont(monofont)
593
 
                self.editBoxes[-1].setAcceptRichText(False)
594
 
                self.connect(self.editBoxes[-1], SIGNAL('textChanged()'), self.updateLivePreviewBox)
595
 
                self.connect(self.editBoxes[-1], SIGNAL('undoAvailable(bool)'), self.actionUndo, SLOT('setEnabled(bool)'))
596
 
                self.connect(self.editBoxes[-1], SIGNAL('redoAvailable(bool)'), self.actionRedo, SLOT('setEnabled(bool)'))
597
 
                self.connect(self.editBoxes[-1], SIGNAL('copyAvailable(bool)'), self.enableCopy)
598
 
                self.connect(self.editBoxes[-1].document(), SIGNAL('modificationChanged(bool)'), self.modificationChanged)
599
 
                return self.getSplitter(-1)
600
 
        
601
 
        def closeTab(self, ind):
602
 
                if self.maybeSave(ind):
603
 
                        if self.tabWidget.count() == 1:
604
 
                                self.tabWidget.addTab(self.createTab(""), self.tr("New document"))
605
 
                        del self.editBoxes[ind]
606
 
                        del self.previewBoxes[ind]
607
 
                        del self.highlighters[ind]
608
 
                        del self.fileNames[ind]
609
 
                        del self.apc[ind]
610
 
                        del self.alpc[ind]
611
 
                        del self.aptc[ind]
612
 
                        del self.gDocsEntries[ind]
613
 
                        self.tabWidget.removeTab(ind)
614
 
        
615
 
        def changeIndex(self, ind):
616
 
                if ind > -1:
617
 
                        self.actionPlainText.setChecked(self.aptc[ind])
618
 
                        self.enablePlainTextMain(self.aptc[ind])
619
 
                        self.actionUndo.setEnabled(self.editBoxes[ind].document().isUndoAvailable())
620
 
                        self.actionRedo.setEnabled(self.editBoxes[ind].document().isRedoAvailable())
621
 
                        self.actionCopy.setEnabled(self.editBoxes[ind].textCursor().hasSelection())
622
 
                        self.actionCut.setEnabled(self.editBoxes[ind].textCursor().hasSelection())
623
 
                        self.actionPreview.setChecked(self.apc[ind])
624
 
                        self.actionLivePreview.setChecked(self.alpc[ind])
625
 
                        self.editBar.setDisabled(self.apc[ind])
626
 
                self.ind = ind
627
 
                if self.fileNames[ind]:
628
 
                        self.setCurrentFile()
629
 
                else:
630
 
                        try:
631
 
                                self.setWindowTitle(self.tr('New document') + '[*] ' + QChar(0x2014) + ' ' + app_name)
632
 
                        except:
633
 
                                # For Python 3
634
 
                                self.setWindowTitle(self.tr('New document') + '[*] \u2014 ' + app_name)
635
 
                self.modificationChanged(self.editBoxes[ind].document().isModified())
636
 
                self.livePreviewEnabled = self.alpc[ind]
637
 
                if self.alpc[ind]:
638
 
                        self.enableLivePreview(True)
639
 
                self.editBoxes[self.ind].setFocus(Qt.OtherFocusReason)
640
 
        
641
 
        def changeFont(self):
642
 
                if not self.font:
643
 
                        self.font = QFont()
644
 
                fd = QFontDialog.getFont(self.font, self)
645
 
                if fd[1]:
646
 
                        self.font = QFont()
647
 
                        self.font.setFamily(fd[0].family())
648
 
                        settings.setValue('font', fd[0].family())
649
 
                        self.font.setPointSize(fd[0].pointSize())
650
 
                        settings.setValue('fontSize', fd[0].pointSize())
651
 
                        self.updatePreviewBox()
652
 
        
653
 
        def preview(self, viewmode):
654
 
                self.apc[self.ind] = viewmode
655
 
                if self.actionLivePreview.isChecked():
656
 
                        self.actionLivePreview.setChecked(False)
657
 
                        return self.enableLivePreview(False)
658
 
                self.editBar.setDisabled(viewmode)
659
 
                self.editBoxes[self.ind].setVisible(not viewmode)
660
 
                self.previewBoxes[self.ind].setVisible(viewmode)
661
 
                if viewmode:
662
 
                        self.updatePreviewBox()
663
 
        
664
 
        def enableLivePreview(self, livemode):
665
 
                self.livePreviewEnabled = livemode
666
 
                self.alpc[self.ind] = livemode
667
 
                self.apc[self.ind] = livemode
668
 
                self.actionPreview.setChecked(livemode)
669
 
                self.editBar.setEnabled(True)
670
 
                self.previewBoxes[self.ind].setVisible(livemode)
671
 
                self.editBoxes[self.ind].setVisible(True)
672
 
                if livemode:
673
 
                        self.updatePreviewBox()
674
 
        
675
 
        def enableWebKit(self, enable):
676
 
                self.useWebKit = enable
677
 
                if enable:
678
 
                        settings.setValue('useWebKit', True)
679
 
                else:
680
 
                        settings.remove('useWebKit')
681
 
                oldind = self.ind
682
 
                self.tabWidget.clear()
683
 
                for self.ind in range(len(self.editBoxes)):
684
 
                        if enable:
685
 
                                self.previewBoxes[self.ind] = QWebView()
686
 
                        else:
687
 
                                self.previewBoxes[self.ind] = QTextEdit()
688
 
                                self.previewBoxes[self.ind].setReadOnly(True)
689
 
                        splitter = self.getSplitter(self.ind)
690
 
                        self.tabWidget.addTab(splitter, self.getDocumentTitle(baseName=True))
691
 
                        self.updatePreviewBox()
692
 
                        self.previewBoxes[self.ind].setVisible(self.apc[self.ind])
693
 
                self.ind = oldind
694
 
                self.tabWidget.setCurrentIndex(self.ind)
695
 
        
696
 
        def enableCopy(self, copymode):
697
 
                self.actionCopy.setEnabled(copymode)
698
 
                self.actionCut.setEnabled(copymode)
699
 
        
700
 
        def enableFullScreen(self, yes):
701
 
                if yes:
702
 
                        self.showFullScreen()
703
 
                else:
704
 
                        self.showNormal()
705
 
        
706
 
        def keyPressEvent(self, e):
707
 
                v = not self.menubar.isVisible()
708
 
                if e.key() == Qt.Key_F12 and e.modifiers() & Qt.ShiftModifier:
709
 
                        self.menubar.setVisible(v)
710
 
                        self.toolBar.setVisible(v)
711
 
                        self.editBar.setVisible(v)
712
 
                elif e.key() == Qt.Key_F11:
713
 
                        if v:
714
 
                                n = not self.actionFullScreen.isChecked()
715
 
                                self.actionFullScreen.setChecked(n)
716
 
                                self.enableFullScreen(n)
717
 
        
718
 
        def enableSC(self, yes):
719
 
                global dictionary
720
 
                if yes:
721
 
                        if self.sl:
722
 
                                try:
723
 
                                        dictionary = enchant.Dict(self.sl)
724
 
                                except Exception as e:
725
 
                                        QMessageBox.warning(self, app_name, str(e))
726
 
                                        dictionary = enchant.Dict()
727
 
                        else:
728
 
                                dictionary = enchant.Dict()
729
 
                        settings.setValue('spellCheck', True)
730
 
                else:
731
 
                        dictionary = None
732
 
                        settings.remove('spellCheck')
733
 
                for highlighter in self.highlighters:
734
 
                        highlighter.rehighlight()
735
 
        
736
 
        def changeLocale(self):
737
 
                if self.sl == None:
738
 
                        text = ""
739
 
                else:
740
 
                        text = self.sl
741
 
                sl, ok = QInputDialog.getText(self, app_name, self.tr('Enter locale name (example: en_US)'), QLineEdit.Normal, text)
742
 
                if ok and sl:
743
 
                        try:
744
 
                                sl = str(sl)
745
 
                        except:
746
 
                                pass
747
 
                        else:
748
 
                                self.sl = sl
749
 
                                self.enableSC(self.actionEnableSC.isChecked())
750
 
                elif not sl:
751
 
                        self.sl = None
752
 
                        self.enableSC(self.actionEnableSC.isChecked())
753
 
        
754
 
        def searchBarVisibilityChanged(self, visible):
755
 
                self.actionSearch.setChecked(visible)
756
 
                if visible:
757
 
                        self.searchEdit.setFocus(Qt.ShortcutFocusReason)
758
 
        
759
 
        def find(self, back=False):
760
 
                flags = 0
761
 
                if back:
762
 
                        flags = QTextDocument.FindBackward
763
 
                if self.csBox.isChecked():
764
 
                        flags = flags | QTextDocument.FindCaseSensitively
765
 
                text = self.searchEdit.text()
766
 
                if not self.findMain(text, flags):
767
 
                        if text in self.editBoxes[self.ind].toPlainText():
768
 
                                cursor = self.editBoxes[self.ind].textCursor()
769
 
                                if back:
770
 
                                        cursor.movePosition(QTextCursor.End)
771
 
                                else:
772
 
                                        cursor.movePosition(QTextCursor.Start)
773
 
                                self.editBoxes[self.ind].setTextCursor(cursor)
774
 
                                self.findMain(text, flags)
775
 
        
776
 
        def findMain(self, text, flags):
777
 
                if flags:
778
 
                        return self.editBoxes[self.ind].find(text, flags)
779
 
                else:
780
 
                        return self.editBoxes[self.ind].find(text)
781
 
        
782
 
        def updatePreviewBox(self):
783
 
                self.previewBlocked = False
784
 
                pb = self.previewBoxes[self.ind]
785
 
                textedit = isinstance(pb, QTextEdit)
786
 
                if self.ss and textedit:
787
 
                        pb.document().setDefaultStyleSheet(self.ss)
788
 
                if self.actionPlainText.isChecked():
789
 
                        if textedit:
790
 
                                pb.setPlainText(self.editBoxes[self.ind].toPlainText())
791
 
                        else:
792
 
                                td = QTextDocument()
793
 
                                td.setPlainText(self.editBoxes[self.ind].toPlainText())
794
 
                                pb.setHtml(td.toHtml())
795
 
                else:
796
 
                        try:
797
 
                                pb.setHtml(self.parseText())
798
 
                        except Exception as e:
799
 
                                self.printError(e)
800
 
                if self.font and textedit:
801
 
                        pb.document().setDefaultFont(self.font)
802
 
        
803
 
        def updateLivePreviewBox(self):
804
 
                if self.actionLivePreview.isChecked() and self.previewBlocked == False:
805
 
                        self.previewBlocked = True
806
 
                        QTimer.singleShot(1000, self.updatePreviewBox)
807
 
        
808
 
        def startWpgen(self):
809
 
                if self.fileNames[self.ind] == "":
810
 
                        QMessageBox.warning(self, app_name, self.tr("Please, save the file somewhere."))
811
 
                elif wpgen:
812
 
                        if not (QDir("html").exists() and QFile.exists("template.html")):
813
 
                                Popen((wpgen, 'init')).wait()
814
 
                        Popen([wpgen, 'updateall']).wait()
815
 
                        msgBox = QMessageBox(QMessageBox.Information, app_name, \
816
 
                        self.tr("Webpages saved in <code>html</code> directory."), QMessageBox.Ok)
817
 
                        showButton = msgBox.addButton(self.tr("Show directory"), QMessageBox.AcceptRole)
818
 
                        msgBox.exec_()
819
 
                        if msgBox.clickedButton() == showButton:
820
 
                                QDesktopServices.openUrl(QUrl.fromLocalFile(QDir('html').absolutePath()))
821
 
                else:
822
 
                        QMessageBox.error(self, app_name, self.tr("Webpages generator is not installed!"))
823
 
        
824
 
        def showInDir(self):
825
 
                if self.fileNames[self.ind]:
826
 
                        QDesktopServices.openUrl(QUrl.fromLocalFile(QFileInfo(self.fileNames[self.ind]).path()))
827
 
                else:
828
 
                        QMessageBox.warning(self, app_name, self.tr("Please, save the file somewhere."))
829
 
        
830
 
        def setCurrentFile(self):
831
 
                self.setWindowTitle("")
832
 
                self.tabWidget.setTabText(self.ind, self.getDocumentTitle(baseName=True))
833
 
                self.setWindowFilePath(self.fileNames[self.ind])
834
 
                files = readListFromSettings(settings, "recentFileList")
835
 
                try:
836
 
                        files.prepend(self.fileNames[self.ind])
837
 
                        files.removeDuplicates()
838
 
                except:
839
 
                        # For Python 3
840
 
                        while self.fileNames[self.ind] in files:
841
 
                                files.remove(self.fileNames[self.ind])
842
 
                        files.insert(0, self.fileNames[self.ind])
843
 
                if len(files) > 10:
844
 
                        del files[10:]
845
 
                writeListToSettings(settings, "recentFileList", files)
846
 
                QDir.setCurrent(QFileInfo(self.fileNames[self.ind]).dir().path())
847
 
        
848
 
        def createNew(self):
849
 
                self.tabWidget.addTab(self.createTab(""), self.tr("New document"))
850
 
                self.ind = self.tabWidget.count()-1
851
 
                self.tabWidget.setCurrentIndex(self.ind)
852
 
        
853
 
        def updateRecentFiles(self):
854
 
                self.menuRecentFiles.clear()
855
 
                self.recentFilesActions = []
856
 
                filesOld = readListFromSettings(settings, "recentFileList")
857
 
                files = []
858
 
                for f in filesOld:
859
 
                        if QFile.exists(f):
860
 
                                files.append(f)
861
 
                                self.recentFilesActions.append(self.act(f, trig=self.openFunction(f)))
862
 
                writeListToSettings(settings, "recentFileList", files)
863
 
                for action in self.recentFilesActions:
864
 
                        self.menuRecentFiles.addAction(action)
865
 
        
866
 
        def openFunction(self, fileName):
867
 
                return lambda: self.openFileWrapper(fileName)
868
 
        
869
 
        def extensionFuntion(self, data):
870
 
                return lambda: \
871
 
                self.runExtensionCommand(data['Exec'], data['FileFilter'], data['DefaultExtension'])
872
 
        
873
 
        def getExportExtensionsList(self):
874
 
                extensions = []
875
 
                for extsprefix in ('/usr', QDir.homePath()+'/.local'):
876
 
                        extsdir = QDir(extsprefix+'/share/retext/export-extensions/')
877
 
                        if extsdir.exists():
878
 
                                for fileInfo in extsdir.entryInfoList(['*.desktop', '*.ini'], QDir.Files | QDir.Readable):
879
 
                                        extensions.append(self.readExtension(fileInfo.filePath()))
880
 
                locale = QLocale.system().name()
881
 
                self.extensionActions = []
882
 
                for extension in extensions:
883
 
                        try:
884
 
                                if ('Name[%s]' % locale) in extension:
885
 
                                        name = extension['Name[%s]' % locale]
886
 
                                elif ('Name[%s]' % locale.split('_')[0]) in extension:
887
 
                                        name = extension['Name[%s]' % locale.split('_')[0]]
888
 
                                else:
889
 
                                        name = extension['Name']
890
 
                                data = {}
891
 
                                for prop in ('FileFilter', 'DefaultExtension', 'Exec'):
892
 
                                        if 'X-ReText-'+prop in extension:
893
 
                                                data[prop] = extension['X-ReText-'+prop]
894
 
                                        elif prop in extension:
895
 
                                                data[prop] = extension[prop]
896
 
                                        else:
897
 
                                                data[prop] = ''
898
 
                                action = self.act(name, trig=self.extensionFuntion(data))
899
 
                                if 'Icon' in extension:
900
 
                                        action.setIcon(self.actIcon(extension['Icon']))
901
 
                                mimetype = extension['MimeType'] if 'MimeType' in extension else None
902
 
                        except KeyError:
903
 
                                print('Failed to parse extension: Name is required')
904
 
                        else:
905
 
                                self.extensionActions.append((action, mimetype))
906
 
        
907
 
        def updateExtensionsVisibility(self):
908
 
                for action in self.extensionActions:
909
 
                        if self.actionPlainText.isChecked():
910
 
                                action[0].setEnabled(False)
911
 
                                continue
912
 
                        mimetype = action[1]
913
 
                        if mimetype == None:
914
 
                                enabled = True
915
 
                        elif self.getParser() == PARSER_MARKDOWN:
916
 
                                enabled = (mimetype in ("text/x-retext-markdown", "text/x-markdown"))
917
 
                        elif self.getParser() == PARSER_DOCUTILS:
918
 
                                enabled = (mimetype in ("text/x-retext-rst", "text/x-rst"))
919
 
                        elif self.getParser() == PARSER_HTML:
920
 
                                enabled = (mimetype == "text/html")
921
 
                        else:
922
 
                                enabled = False
923
 
                        action[0].setEnabled(enabled)
924
 
        
925
 
        def readExtension(self, fileName):
926
 
                extFile = QFile(fileName)
927
 
                extFile.open(QIODevice.ReadOnly)
928
 
                extension = {}
929
 
                stream = QTextStream(extFile)
930
 
                while not stream.atEnd():
931
 
                        line = stream.readLine()
932
 
                        try:
933
 
                                line = unicode(line)
934
 
                        except:
935
 
                                # Not needed for Python 3
936
 
                                pass
937
 
                        if '=' in line:
938
 
                                index = line.index('=')
939
 
                                extension[line[:index].rstrip()] = line[index+1:].lstrip()
940
 
                extFile.close()
941
 
                return extension
942
 
        
943
 
        def openFile(self):
944
 
                fileNames = QFileDialog.getOpenFileNames(self, self.tr("Select one or several files to open"), "", \
945
 
                self.tr("Supported files")+" (*.re *.md *.markdown *.mdown *.mkd *.mkdn *.rst *.rest *.txt *.html *.htm);;"+self.tr("All files (*)"))
946
 
                for fileName in fileNames:
947
 
                        self.openFileWrapper(fileName)
948
 
        
949
 
        def openFileWrapper(self, fileName):
950
 
                if not fileName:
951
 
                        return
952
 
                fileName = QFileInfo(fileName).canonicalFilePath()
953
 
                exists = False
954
 
                for i in range(self.tabWidget.count()):
955
 
                        if self.fileNames[i] == fileName:
956
 
                                exists = True
957
 
                                ex = i
958
 
                if exists:
959
 
                        self.tabWidget.setCurrentIndex(ex)
960
 
                else:
961
 
                        if self.fileNames[self.ind] or self.editBoxes[self.ind].toPlainText() \
962
 
                        or self.editBoxes[self.ind].document().isModified():
963
 
                                self.tabWidget.addTab(self.createTab(""), "")
964
 
                                self.ind = self.tabWidget.count()-1
965
 
                                self.tabWidget.setCurrentIndex(self.ind)
966
 
                        self.fileNames[self.ind] = fileName
967
 
                        self.openFileMain()
968
 
        
969
 
        def openFileMain(self):
970
 
                if QFile.exists(self.fileNames[self.ind]):
971
 
                        openfile = QFile(self.fileNames[self.ind])
972
 
                        openfile.open(QIODevice.ReadOnly)
973
 
                        html = QTextStream(openfile).readAll()
974
 
                        openfile.close()
975
 
                        self.editBoxes[self.ind].setPlainText(html)
976
 
                        suffix = QFileInfo(self.fileNames[self.ind]).suffix()
977
 
                        pt = suffix not in ('re', 'md', 'markdown', 'mdown', 'mkd', 'mkdn', 'rst', 'rest', 'html', 'htm')
978
 
                        if settings.contains('autoPlainText'):
979
 
                                if not readFromSettings(settings, 'autoPlainText', bool):
980
 
                                        pt = False
981
 
                        self.actionPlainText.setChecked(pt)
982
 
                        self.enablePlainText(pt)
983
 
                        self.setCurrentFile()
984
 
                        self.setWindowModified(False)
985
 
        
986
 
        def saveFile(self):
987
 
                self.saveFileMain(dlg=False)
988
 
        
989
 
        def saveFileAs(self):
990
 
                self.saveFileMain(dlg=True)
991
 
        
992
 
        def saveAll(self):
993
 
                oldind = self.ind
994
 
                for self.ind in range(self.tabWidget.count()):
995
 
                        if self.fileNames[self.ind] and QFileInfo(self.fileNames[self.ind]).isWritable():
996
 
                                self.saveFileWrapper(self.fileNames[self.ind])
997
 
                                self.editBoxes[self.ind].document().setModified(False)
998
 
                self.ind = oldind
999
 
        
1000
 
        def saveFileMain(self, dlg):
1001
 
                if (not self.fileNames[self.ind]) or dlg:
1002
 
                        if self.actionPlainText.isChecked():
1003
 
                                defaultExt = self.tr("Plain text (*.txt)")
1004
 
                                ext = ".txt"
1005
 
                        elif self.getParser() == PARSER_DOCUTILS:
1006
 
                                defaultExt = self.tr("ReStructuredText files")+" (*.rest *.rst *.txt)"
1007
 
                                ext = ".rst"
1008
 
                        elif self.getParser() == PARSER_HTML:
1009
 
                                defaultExt = self.tr("HTML files")+" (*.html *.htm)"
1010
 
                                ext = ".html"
1011
 
                        else:
1012
 
                                defaultExt = self.tr("Markdown files")+" (*.re *.md *.markdown *.mdown *.mkd *.mkdn *.txt)"
1013
 
                                ext = ".mkd"
1014
 
                                if settings.contains('defaultExt'):
1015
 
                                        ext = readFromSettings(settings, 'defaultExt', str)
1016
 
                        self.fileNames[self.ind] = QFileDialog.getSaveFileName(self, self.tr("Save file"), "", defaultExt)
1017
 
                        if self.fileNames[self.ind] and not QFileInfo(self.fileNames[self.ind]).suffix():
1018
 
                                self.fileNames[self.ind] += ext
1019
 
                if QFileInfo(self.fileNames[self.ind]).isWritable() or not QFile.exists(self.fileNames[self.ind]):
1020
 
                        if self.fileNames[self.ind]:
1021
 
                                self.saveFileWrapper(self.fileNames[self.ind])
1022
 
                                self.setCurrentFile()
1023
 
                                self.editBoxes[self.ind].document().setModified(False)
1024
 
                                self.setWindowModified(False)
1025
 
                else:
1026
 
                        self.setWindowModified(self.isWindowModified())
1027
 
                        QMessageBox.warning(self, app_name, self.tr("Cannot save to file because it is read-only!"))
1028
 
        
1029
 
        def saveFileWrapper(self, fn):
1030
 
                savefile = QFile(fn)
1031
 
                savefile.open(QIODevice.WriteOnly)
1032
 
                savestream = QTextStream(savefile)
1033
 
                savestream << self.editBoxes[self.ind].toPlainText()
1034
 
                savefile.close()
1035
 
        
1036
 
        def saveHtml(self, fileName):
1037
 
                if not QFileInfo(fileName).suffix():
1038
 
                        fileName += ".html"
1039
 
                try:
1040
 
                        text = self.parseText()
1041
 
                except Exception as e:
1042
 
                        return self.printError(e)
1043
 
                htmlFile = QFile(fileName)
1044
 
                htmlFile.open(QIODevice.WriteOnly)
1045
 
                html = QTextStream(htmlFile)
1046
 
                if self.getParser() == PARSER_HTML:
1047
 
                        html << text << "\n"
1048
 
                        htmlFile.close()
1049
 
                        return
1050
 
                html << '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n'
1051
 
                html << '<html>\n<head>\n'
1052
 
                html << '  <meta http-equiv="content-type" content="text/html; charset=utf-8">\n'
1053
 
                html << '  <meta name="generator" content="%s %s">\n' % (app_name, app_version)
1054
 
                html << '  <title>' + self.getDocumentTitle() + '</title>\n'
1055
 
                html << '</head>\n<body>\n'
1056
 
                html << text
1057
 
                html << '\n</body>\n</html>\n'
1058
 
                htmlFile.close()
1059
 
        
1060
 
        def textDocument(self):
1061
 
                if not self.actionPlainText.isChecked():
1062
 
                        text = self.parseText()
1063
 
                td = QTextDocument()
1064
 
                td.setMetaInformation(QTextDocument.DocumentTitle, self.getDocumentTitle())
1065
 
                if self.ss:
1066
 
                        td.setDefaultStyleSheet(self.ss)
1067
 
                if self.actionPlainText.isChecked():
1068
 
                        td.setPlainText(self.editBoxes[self.ind].toPlainText())
1069
 
                else:
1070
 
                        td.setHtml('<html><body>'+text+'</body></html>')
1071
 
                if self.font:
1072
 
                        td.setDefaultFont(self.font)
1073
 
                return td
1074
 
        
1075
 
        def saveOdf(self):
1076
 
                try:
1077
 
                        document = self.textDocument()
1078
 
                except Exception as e:
1079
 
                        self.printError(e)
1080
 
                        return
1081
 
                fileName = QFileDialog.getSaveFileName(self, self.tr("Export document to ODT"), "", self.tr("OpenDocument text files (*.odt)"))
1082
 
                if not QFileInfo(fileName).suffix():
1083
 
                        fileName += ".odt"
1084
 
                writer = QTextDocumentWriter(fileName)
1085
 
                writer.setFormat("odf")
1086
 
                writer.write(document)
1087
 
        
1088
 
        def saveFilePerfect(self):
1089
 
                fileName = None
1090
 
                fileName = QFileDialog.getSaveFileName(self, self.tr("Save file"), "", self.tr("HTML files (*.html *.htm)"))
1091
 
                if fileName:
1092
 
                        self.saveHtml(fileName)
1093
 
        
1094
 
        def getDocumentForPrint(self):
1095
 
                if self.useWebKit:
1096
 
                        return self.previewBoxes[self.ind]
1097
 
                try:
1098
 
                        return self.textDocument()
1099
 
                except Exception as e:
1100
 
                        self.printError(e)
1101
 
                        return None
1102
 
        
1103
 
        def standardPrinter(self):
1104
 
                printer = QPrinter(QPrinter.HighResolution)
1105
 
                printer.setDocName(self.getDocumentTitle())
1106
 
                printer.setCreator(app_name+" "+app_version)
1107
 
                return printer
1108
 
        
1109
 
        def savePdf(self):
1110
 
                document = self.getDocumentForPrint()
1111
 
                if document == None:
1112
 
                        return
1113
 
                fileName = QFileDialog.getSaveFileName(self, self.tr("Export document to PDF"), "", self.tr("PDF files (*.pdf)"))
1114
 
                if fileName:
1115
 
                        if not QFileInfo(fileName).suffix():
1116
 
                                fileName += ".pdf"
1117
 
                        printer = self.standardPrinter()
1118
 
                        printer.setOutputFormat(QPrinter.PdfFormat)
1119
 
                        printer.setOutputFileName(fileName)
1120
 
                        document.print_(printer)
1121
 
        
1122
 
        def printFile(self):
1123
 
                document = self.getDocumentForPrint()
1124
 
                if document == None:
1125
 
                        return
1126
 
                printer = self.standardPrinter()
1127
 
                dlg = QPrintDialog(printer, self)
1128
 
                dlg.setWindowTitle(self.tr("Print document"))
1129
 
                if (dlg.exec_() == QDialog.Accepted):
1130
 
                        document.print_(printer)
1131
 
        
1132
 
        def printPreview(self):
1133
 
                document = self.getDocumentForPrint()
1134
 
                if document == None:
1135
 
                        return
1136
 
                printer = self.standardPrinter()
1137
 
                preview = QPrintPreviewDialog(printer, self)
1138
 
                self.connect(preview, SIGNAL("paintRequested(QPrinter*)"), document.print_)
1139
 
                preview.exec_()
1140
 
        
1141
 
        def runExtensionCommand(self, command, filefilter='', defaultext=''):
1142
 
                of = ('%of' in command)
1143
 
                html = ('%html' in command)
1144
 
                if of:
1145
 
                        if defaultext and not filefilter:
1146
 
                                filefilter = '*'+defaultext
1147
 
                        fileName = QFileDialog.getSaveFileName(self, self.tr('Export document'), '', filefilter)
1148
 
                        if not fileName:
1149
 
                                return
1150
 
                        if defaultext and not QFileInfo(fileName).suffix():
1151
 
                                fileName += defaultext
1152
 
                if html:
1153
 
                        tmpname = '.retext-temp.html'
1154
 
                        self.saveHtml(tmpname)
1155
 
                else:
1156
 
                        tmpname = '.retext-temp.rst' if self.getParser() == PARSER_DOCUTILS else '.retext-temp.mkd'
1157
 
                        self.saveFileWrapper(tmpname)
1158
 
                command = command.replace('%of', 'out'+defaultext)
1159
 
                command = command.replace('%html' if html else '%if', tmpname)
1160
 
                args = str(command).split()
1161
 
                try:
1162
 
                        Popen(args).wait()
1163
 
                except Exception as error:
1164
 
                        errorstr = str(error)
1165
 
                        try:
1166
 
                                errorstr = QString.fromUtf8(errorstr)
1167
 
                        except:
1168
 
                                # Not needed for Python 3
1169
 
                                pass
1170
 
                        QMessageBox.warning(self, app_name, self.tr('Failed to execute the command:') + '\n' + errorstr)
1171
 
                QFile(tmpname).remove()
1172
 
                if of:
1173
 
                        QFile('out'+defaultext).rename(fileName)
1174
 
        
1175
 
        def otherExport(self):
1176
 
                if self.actionPlainText.isChecked():
1177
 
                        return QMessageBox.warning(self, app_name, self.tr('This function is not available in Plain text mode!'))
1178
 
                settings.beginGroup('Export')
1179
 
                types = settings.allKeys()
1180
 
                item, ok = QInputDialog.getItem(self, app_name, self.tr('Select type'), types, 0, False)
1181
 
                if not ok:
1182
 
                        return settings.endGroup()
1183
 
                command = readFromSettings(settings, item, str)
1184
 
                settings.endGroup()
1185
 
                self.runExtensionCommand(command, defaultext='.'+item)
1186
 
        
1187
 
        def getDocumentTitle(self, baseName=False):
1188
 
                """Ensure that parseText() is called before this function!
1189
 
                If 'baseName' is set to True, file basename will be used."""
1190
 
                realTitle = ''
1191
 
                try:
1192
 
                        text = unicode(self.editBoxes[self.ind].toPlainText())
1193
 
                except:
1194
 
                        # For Python 3
1195
 
                        text = self.editBoxes[self.ind].toPlainText()
1196
 
                if not self.actionPlainText.isChecked():
1197
 
                        parser = self.getParser()
1198
 
                        if parser == PARSER_DOCUTILS:
1199
 
                                realTitle = publish_parts(text, writer_name='html')['title']
1200
 
                        elif parser == PARSER_MARKDOWN:
1201
 
                                try:
1202
 
                                        realTitle = str.join(' ', md.Meta['title'])
1203
 
                                except:
1204
 
                                        # Meta extension not installed
1205
 
                                        pass
1206
 
                if realTitle and not baseName:
1207
 
                        return realTitle
1208
 
                elif self.fileNames[self.ind]:
1209
 
                        fileinfo = QFileInfo(self.fileNames[self.ind])
1210
 
                        basename = fileinfo.completeBaseName()
1211
 
                        return (basename if basename else fileinfo.fileName())
1212
 
                else:
1213
 
                        return self.tr("New document")
1214
 
        
1215
 
        def saveGDocs(self):
1216
 
                login = passwd = ''
1217
 
                if settings.contains('GDocsLogin') and settings.contains('GDocsPasswd'):
1218
 
                        login = readFromSettings(settings, 'GDocsLogin', str)
1219
 
                        passwd = readFromSettings(settings, 'GDocsPasswd', str)
1220
 
                if self.gDocsEntries[self.ind] == None:
1221
 
                        loginDialog = LogPassDialog(login, passwd)
1222
 
                        if loginDialog.exec_() == QDialog.Accepted:
1223
 
                                login = loginDialog.loginEdit.text()
1224
 
                                passwd = loginDialog.passEdit.text()
1225
 
                        else:
1226
 
                                return
1227
 
                if self.actionPlainText.isChecked():
1228
 
                        tempFile = '.retext-temp.txt'
1229
 
                        contentType = 'text/plain'
1230
 
                        self.saveFileWrapper(tempFile)
1231
 
                else:
1232
 
                        tempFile = '.retext-temp.html'
1233
 
                        contentType = 'text/html'
1234
 
                        self.saveHtml(tempFile)
1235
 
                gdClient = gdata.docs.client.DocsClient(source=app_name)
1236
 
                gdClient.ssl = True
1237
 
                try:
1238
 
                        try:
1239
 
                                gdClient.ClientLogin(unicode(login), unicode(passwd), gdClient.source)
1240
 
                        except NameError:
1241
 
                                # For Python 3
1242
 
                                gdClient.ClientLogin(login, passwd, gdClient.source)
1243
 
                except gdata.client.BadAuthentication:
1244
 
                        QFile(tempFile).remove()
1245
 
                        return QMessageBox.warning(self, app_name, self.tr("Incorrect user name or password!"))
1246
 
                except:
1247
 
                        QFile(tempFile).remove()
1248
 
                        return QMessageBox.warning(self, app_name, \
1249
 
                        self.tr("Authentification failed, please check your internet connection!"))
1250
 
                settings.setValue("GDocsLogin", login)
1251
 
                settings.setValue("GDocsPasswd", passwd)
1252
 
                try:
1253
 
                        title = unicode(self.getDocumentTitle())
1254
 
                except:
1255
 
                        # For Python 3
1256
 
                        title = self.getDocumentTitle()
1257
 
                ms = MediaSource(file_path=tempFile, content_type=contentType)
1258
 
                entry = self.gDocsEntries[self.ind]
1259
 
                if entry:
1260
 
                        entry.title.text = title
1261
 
                        entry = gdClient.Update(entry, media_source=ms, force=True)
1262
 
                else:
1263
 
                        try:
1264
 
                                resource = gdata.docs.data.Resource(title=title)
1265
 
                                entry = gdClient.CreateResource(resource, media=ms)
1266
 
                        except AttributeError:
1267
 
                                # For old gdata versions
1268
 
                                entry = gdClient.Upload(ms, title)
1269
 
                QDesktopServices.openUrl(QUrl(entry.GetAlternateLink().href))
1270
 
                self.gDocsEntries[self.ind] = entry
1271
 
                QFile(tempFile).remove()
1272
 
        
1273
 
        def autoSaveActive(self):
1274
 
                return self.autoSave and self.fileNames[self.ind] and \
1275
 
                QFileInfo(self.fileNames[self.ind]).isWritable()
1276
 
        
1277
 
        def modificationChanged(self, changed):
1278
 
                if self.autoSaveActive():
1279
 
                        changed = False
1280
 
                self.actionSave.setEnabled(changed)
1281
 
                self.setWindowModified(changed)
1282
 
        
1283
 
        def clipboardDataChanged(self):
1284
 
                self.actionPaste.setEnabled(qApp.clipboard().mimeData().hasText())
1285
 
        
1286
 
        def insertChars(self, chars):
1287
 
                tc = self.editBoxes[self.ind].textCursor()
1288
 
                if tc.hasSelection:
1289
 
                        tc.insertText(chars+tc.selectedText()+chars)
1290
 
                else:
1291
 
                        tc.insertText(chars)
1292
 
        
1293
 
        def insertTag(self, num):
1294
 
                if num:
1295
 
                        ut = self.usefulTags[num-1]
1296
 
                        hc = not ut in ('td', 'tr')
1297
 
                        arg = ''
1298
 
                        if ut == 'span':
1299
 
                                arg = ' style=""'
1300
 
                        tc = self.editBoxes[self.ind].textCursor()
1301
 
                        if hc:
1302
 
                                toinsert = '<'+ut+arg+'>'+tc.selectedText()+'</'+ut+'>'
1303
 
                                tc.insertText(toinsert)
1304
 
                        else:
1305
 
                                tc.insertText('<'+ut+arg+'>'+tc.selectedText())
1306
 
                self.tagsBox.setCurrentIndex(0)
1307
 
        
1308
 
        def insertSymbol(self, num):
1309
 
                if num:
1310
 
                        self.editBoxes[self.ind].insertPlainText('&'+self.usefulChars[num-1]+';')
1311
 
                self.symbolBox.setCurrentIndex(0)
1312
 
        
1313
 
        def maybeSave(self, ind):
1314
 
                if self.autoSaveActive():
1315
 
                        self.saveFileWrapper(self.fileNames[self.ind])
1316
 
                        return True
1317
 
                if not self.editBoxes[ind].document().isModified():
1318
 
                        return True
1319
 
                self.tabWidget.setCurrentIndex(ind)
1320
 
                ret = QMessageBox.warning(self, app_name, self.tr("The document has been modified.\nDo you want to save your changes?"), \
1321
 
                QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel)
1322
 
                if ret == QMessageBox.Save:
1323
 
                        self.saveFileMain(False)
1324
 
                        return True
1325
 
                elif ret == QMessageBox.Cancel:
1326
 
                        return False
1327
 
                return True
1328
 
        
1329
 
        def closeEvent(self, closeevent):
1330
 
                accept = True
1331
 
                for self.ind in range(self.tabWidget.count()):
1332
 
                        if not self.maybeSave(self.ind):
1333
 
                                accept = False
1334
 
                if accept:
1335
 
                        if self.restorePreviewState:
1336
 
                                if self.livePreviewEnabled:
1337
 
                                        settings.setValue('previewState', True)
1338
 
                                else:
1339
 
                                        settings.remove('previewState')
1340
 
                        closeevent.accept()
1341
 
                else:
1342
 
                        closeevent.ignore()
1343
 
        
1344
 
        def viewHtml(self):
1345
 
                HtmlDlg = HtmlDialog(self)
1346
 
                try:
1347
 
                        HtmlDlg.textEdit.setPlainText(self.parseText())
1348
 
                except Exception as e:
1349
 
                        self.printError(e)
1350
 
                        return
1351
 
                winTitle = self.tr('New document')
1352
 
                if self.fileNames[self.ind]:
1353
 
                        winTitle = QFileInfo(self.fileNames[self.ind]).fileName()
1354
 
                try:
1355
 
                        HtmlDlg.setWindowTitle(winTitle+" ("+self.tr("HTML code")+") "+QChar(0x2014)+" "+app_name)
1356
 
                except:
1357
 
                        # For Python 3
1358
 
                        HtmlDlg.setWindowTitle(winTitle+" ("+self.tr("HTML code")+") \u2014 "+app_name)
1359
 
                HtmlDlg.show()
1360
 
                HtmlDlg.raise_()
1361
 
                HtmlDlg.activateWindow()
1362
 
        
1363
 
        def openHelp(self):
1364
 
                QDesktopServices.openUrl(QUrl('http://sourceforge.net/p/retext/home/Help and Support'))
1365
 
        
1366
 
        def aboutDialog(self):
1367
 
                QMessageBox.about(self, self.aboutWindowTitle, \
1368
 
                '<p><b>'+app_name+' '+app_version+'</b><br>'+self.tr('Simple but powerful editor for Markdown and ReStructuredText') \
1369
 
                +'</p><p>'+self.tr('Author: Dmitry Shachnev, 2011') \
1370
 
                +'<br><a href="http://sourceforge.net/p/retext/">'+self.tr('Website') \
1371
 
                +'</a> | <a href="http://daringfireball.net/projects/markdown/syntax">'+self.tr('Markdown syntax') \
1372
 
                +'</a> | <a href="http://docutils.sourceforge.net/docs/user/rst/quickref.html">' \
1373
 
                +self.tr('ReST syntax')+'</a></p>')
1374
 
        
1375
 
        def enablePlainText(self, value):
1376
 
                self.aptc[self.ind] = value
1377
 
                self.enablePlainTextMain(value)
1378
 
                self.updatePreviewBox()
1379
 
        
1380
 
        def enablePlainTextMain(self, value):
1381
 
                self.actionPerfectHtml.setDisabled(value)
1382
 
                self.actionViewHtml.setDisabled(value)
1383
 
                self.tagsBox.setDisabled(value)
1384
 
                self.symbolBox.setDisabled(value)
1385
 
        
1386
 
        def setDocUtilsDefault(self, yes):
1387
 
                self.useDocUtils = yes
1388
 
                if yes:
1389
 
                        settings.setValue('useReST', True)
1390
 
                else:
1391
 
                        settings.remove('useReST')
1392
 
                self.updatePreviewBox()
1393
 
        
1394
 
        def getParser(self):
1395
 
                if self.fileNames[self.ind]:
1396
 
                        suffix = QFileInfo(self.fileNames[self.ind]).suffix()
1397
 
                        if suffix in ('md', 'markdown', 'mdown', 'mkd', 'mkdn', 're'):
1398
 
                                return PARSER_MARKDOWN if use_md else PARSER_NA
1399
 
                        elif suffix in ('rest', 'rst'):
1400
 
                                return PARSER_DOCUTILS if use_docutils else PARSER_NA
1401
 
                        elif suffix in ('html', 'htm'):
1402
 
                                return PARSER_HTML
1403
 
                if not (use_docutils or use_md):
1404
 
                        return PARSER_HTML
1405
 
                elif use_docutils and (self.useDocUtils or not use_md):
1406
 
                        return PARSER_DOCUTILS
1407
 
                else:
1408
 
                        return PARSER_MARKDOWN
1409
 
        
1410
 
        def parseText(self):
1411
 
                try:
1412
 
                        htmltext = unicode(self.editBoxes[self.ind].toPlainText())
1413
 
                except:
1414
 
                        # For Python 3
1415
 
                        htmltext = self.editBoxes[self.ind].toPlainText()
1416
 
                # WpGen directives
1417
 
                htmltext = htmltext.replace('%HTMLDIR%', 'html')
1418
 
                htmltext = htmltext.replace('%\\', '%')
1419
 
                parser = self.getParser()
1420
 
                if parser == PARSER_HTML:
1421
 
                        return htmltext
1422
 
                elif parser == PARSER_DOCUTILS:
1423
 
                        return publish_parts(htmltext, writer_name='html')['body']
1424
 
                elif parser == PARSER_MARKDOWN:
1425
 
                        md.reset()
1426
 
                        return md.convert(htmltext)
1427
 
                else:
1428
 
                        return '<p style="color: red">'\
1429
 
                        +self.tr('Could not parse file contents, check if you have the necessary module installed!')+'</p>'
1430
 
 
1431
 
def main(fileNames):
1432
 
        app = QApplication(sys.argv)
1433
 
        app.setOrganizationName("ReText project")
1434
 
        app.setApplicationName("ReText")
1435
 
        RtTranslator = QTranslator()
1436
 
        if not RtTranslator.load("retext_"+QLocale.system().name(), "locale"):
1437
 
                if not RtTranslator.load("retext_"+QLocale.system().name(), "/usr/share/retext/locale"):
1438
 
                        RtTranslator.load("retext_"+QLocale.system().name(), "/usr/lib/retext")
1439
 
        QtTranslator = QTranslator()
1440
 
        QtTranslator.load("qt_"+QLocale.system().name(), QLibraryInfo.location(QLibraryInfo.TranslationsPath))
1441
 
        app.installTranslator(RtTranslator)
1442
 
        app.installTranslator(QtTranslator)
1443
 
        if settings.contains('appStyleSheet'):
1444
 
                stylename = readFromSettings(settings, 'appStyleSheet', str)
1445
 
                sheetfile = QFile(stylename)
1446
 
                sheetfile.open(QIODevice.ReadOnly)
1447
 
                app.setStyleSheet(QTextStream(sheetfile).readAll())
1448
 
                sheetfile.close()
1449
 
        window = ReTextWindow()
1450
 
        for fileName in fileNames:
1451
 
                try:
1452
 
                        fileName = QString.fromUtf8(fileName)
1453
 
                except:
1454
 
                        # Not needed for Python 3
1455
 
                        pass
1456
 
                if QFile.exists(fileName):
1457
 
                        window.openFileWrapper(fileName)
1458
 
        window.show()
1459
 
        sys.exit(app.exec_())
1460
 
 
1461
 
if __name__ == '__main__':
1462
 
        if len(sys.argv) > 1:
1463
 
                main(sys.argv[1:])
1464
 
        else:
1465
 
                main("")