source: trunk/tools/writing_editor/scripts/writingEditor.py @ 251

Revision 251, 21.0 KB checked in by bretzel_parpg, 10 years ago (diff)

Started on putting options in the dialog map

Line 
1#!/usr/bin/python
2
3#   This file is part of PARPG.
4
5#   PARPG is free software: you can redistribute it and/or modify
6#   it under the terms of the GNU General Public License as published by
7#   the Free Software Foundation, either version 3 of the License, or
8#   (at your option) any later version.
9
10#   PARPG is distributed in the hope that it will be useful,
11#   but WITHOUT ANY WARRANTY; without even the implied warranty of
12#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13#   GNU General Public License for more details.
14
15#   You should have received a copy of the GNU General Public License
16#   along with PARPG.  If not, see <http://www.gnu.org/licenses/>.
17
18import sys, os, codecs
19
20from PyQt4 import QtGui, QtCore
21from ui.editor_ui import Ui_writingEditor
22from ui.popupWindows import *
23from scripts.syntaxHighlight import SyntaxHighlighter
24from scripts.settings import Settings
25from scripts.dialogMap import DialogMap
26
27class WritingEditor(QtGui.QMainWindow):
28    """
29    The main class for the writing editor
30    """
31    def __init__(self, parent=None):
32        """
33        Initialize the editor
34        """
35        QtGui.QWidget.__init__(self, parent)
36       
37        self.settings = Settings()
38        self.settings.readSettingsFromFile('data/options.txt')
39        self.resize(int(self.settings.res_width), int(self.settings.res_height))
40
41        self.ui = Ui_writingEditor()
42        self.ui.setupUi(self)
43        self.dialogMap = DialogMap(self.settings, self.ui.main_edit, self.ui.dialog_map_tab)
44        self.syntax = SyntaxHighlighter(self.ui.main_edit.document())
45        self.syntaxCreated = True
46        self.changes = False
47        self.connectSignals()
48        self.setupMenus()
49
50        self.open_file_name = None
51        self.saveEnabled(False)
52        self.title_asterisk = False
53        self.ui.actionNone.setEnabled(False)
54        self.getRecentItems('data/recent_files.txt')
55
56
57    def setupMenus(self):
58        """
59        Setup the menus:
60        Add the shortcuts to all the menu's and also create the shorcuts
61        Add the images for the icons
62        @return: None
63        """
64        self.ui.actionNew_File.setText('&New File\tCtrl+N')
65        self.ui.actionOpen_File.setText('&Open File\tCtrl+O')
66        self.ui.actionSave.setText('&Save\tCtrl+S')
67        self.ui.actionSave_As.setText('Save &As\tCtrl+Shift+S')
68        self.ui.actionPrint.setText('&Print\tCtrl+P')
69        self.ui.actionExit.setText('&Exit\tCtrl+Q')
70        self.ui.actionUndo.setText('&Undo\tCtrl+Z')
71        self.ui.actionRedo.setText('&Redo\tCtrl+Y')
72        self.ui.actionCopy.setText('&Copy\tCtrl+C')
73        self.ui.actionCut.setText('C&ut\tCtrl+X')
74        self.ui.actionPaste.setText('&Paste\tCtrl+V')
75        self.ui.actionPreferences.setText('P&references\tCtrl+Shift+P')
76        self.ui.actionHelp.setText("&Help\tF1")
77        self.ui.actionAbout.setText('&About\tF2')
78        self.ui.actionNone.setText('None')
79
80        self.ui.actionNew_File.setShortcut(QtGui.QKeySequence('Ctrl+N'))
81        self.ui.actionOpen_File.setShortcut(QtGui.QKeySequence('Ctrl+O'))
82        self.ui.actionSave.setShortcut(QtGui.QKeySequence('Ctrl+S'))
83        self.ui.actionSave_As.setShortcut(QtGui.QKeySequence('Ctrl+Shift+S'))
84        self.ui.actionPrint.setShortcut(QtGui.QKeySequence('Ctrl+P'))
85        self.ui.actionExit.setShortcut(QtGui.QKeySequence('Ctrl+Q'))
86        self.ui.actionUndo.setShortcut(QtGui.QKeySequence('Ctrl+Z'))
87        self.ui.actionRedo.setShortcut(QtGui.QKeySequence('Ctrl+Y'))
88        self.ui.actionCopy.setShortcut(QtGui.QKeySequence('Ctrl+C'))
89        self.ui.actionCut.setShortcut(QtGui.QKeySequence('Ctrl+X'))
90        self.ui.actionPaste.setShortcut(QtGui.QKeySequence('Ctrl+V'))
91        self.ui.actionPreferences.setShortcut(QtGui.QKeySequence('Ctrl+Shift+P'))
92        self.ui.actionHelp.setShortcut(QtGui.QKeySequence('F1'))
93        self.ui.actionAbout.setShortcut(QtGui.QKeySequence('F2'))
94
95        self.ui.actionNew_File.setIcon(self.createIcon('new.png'))
96        self.ui.actionOpen_File.setIcon(self.createIcon('open.png'))
97        self.ui.actionSave.setIcon(self.createIcon('save.png'))
98        self.ui.actionSave_As.setIcon(self.createIcon('save_as.png'))
99        self.ui.actionPrint.setIcon(self.createIcon('printer.png'))
100        self.ui.actionExit.setIcon(self.createIcon('close.png'))
101        self.ui.actionUndo.setIcon(self.createIcon('undo.png'))
102        self.ui.actionRedo.setIcon(self.createIcon('redo.png'))
103        self.ui.actionCopy.setIcon(self.createIcon('copy.png'))
104        self.ui.actionCut.setIcon(self.createIcon('cut.png'))
105        self.ui.actionPaste.setIcon(self.createIcon('paste.png'))
106        self.ui.actionPreferences.setIcon(self.createIcon('preferences.png'))
107        self.ui.actionHelp.setIcon(self.createIcon('help.png'))
108        self.ui.actionAbout.setIcon(self.createIcon('about.png'))
109
110        self.ui.actionNew_File.setStatusTip('Create a new file')
111        self.ui.actionOpen_File.setStatusTip('Open a file')
112        self.ui.actionSave.setStatusTip('Save the open file to disk')
113        self.ui.actionSave_As.setStatusTip('Save the contents of the open file to a new file on the disk')
114        self.ui.actionPrint.setStatusTip('Print the open file')
115        self.ui.actionExit.setStatusTip('Exit the editor')
116        self.ui.actionUndo.setStatusTip('Undo the last action within the text editor')
117        self.ui.actionRedo.setStatusTip('Redo the last action within the text editor')
118        self.ui.actionCopy.setStatusTip('Copy the selected text to the clipboard')
119        self.ui.actionCut.setStatusTip('Delete the selected text and copy it to the clipboard')
120        self.ui.actionPaste.setStatusTip('Paste the text on the clipboard')
121        self.ui.actionPreferences.setStatusTip('Edit preferences with the editor')
122        self.ui.actionHelp.setStatusTip('Help with the editor and scripting language itself')
123        self.ui.actionAbout.setStatusTip('About the editor')
124        self.ui.actionNone.setStatusTip('There are no recent files')
125
126    def connectSignals(self):
127        """
128        Connect all the buttons, widgets, etc to their respective functions
129        @return: None
130        """
131        QtCore.QObject.connect(self.ui.main_tabs, QtCore.SIGNAL("currentChanged(int)"),
132                               self.onTabChanged)
133        QtCore.QObject.connect(self.ui.main_edit, QtCore.SIGNAL("textChanged()"),
134                               self.onTextChanged)
135
136        QtCore.QObject.connect(self.ui.actionNew_File, QtCore.SIGNAL("triggered()"),
137                               self.newFile)
138        QtCore.QObject.connect(self.ui.actionOpen_File, QtCore.SIGNAL("triggered()"),
139                               self.openFile)
140        QtCore.QObject.connect(self.ui.actionSave, QtCore.SIGNAL("triggered()"),
141                               self.saveFile)
142        QtCore.QObject.connect(self.ui.actionPrint, QtCore.SIGNAL("triggered()"),
143                               self.printFile)
144        QtCore.QObject.connect(self.ui.actionExit, QtCore.SIGNAL("triggered()"),
145                               lambda: self.quit('data/recent_files.txt'))
146
147        QtCore.QObject.connect(self.ui.actionCopy, QtCore.SIGNAL("triggered()"),
148                               self.ui.main_edit.copy)
149        QtCore.QObject.connect(self.ui.actionCut, QtCore.SIGNAL("triggered()"),
150                               self.ui.main_edit.cut)
151        QtCore.QObject.connect(self.ui.actionPaste, QtCore.SIGNAL("triggered()"),
152                               self.ui.main_edit.paste)
153        QtCore.QObject.connect(self.ui.actionRedo, QtCore.SIGNAL("triggered()"),
154                               self.ui.main_edit.redo)
155        QtCore.QObject.connect(self.ui.actionUndo, QtCore.SIGNAL("triggered()"),
156                               self.ui.main_edit.undo)
157        QtCore.QObject.connect(self.ui.actionPreferences, QtCore.SIGNAL("triggered()"),
158                               self.createPrefWindow)
159
160        QtCore.QObject.connect(self.ui.actionAbout, QtCore.SIGNAL("triggered()"),
161                               self.createAboutWindow)
162        QtCore.QObject.connect(self.ui.actionHelp, QtCore.SIGNAL("triggered()"),
163                               self.createHelpWindow)
164
165    def onTextChanged(self):
166        """
167        Function called when text is changed
168        """
169        if (self.syntaxCreated):
170            self.syntaxCreated = False
171
172        else:
173            self.saveEnabled(True)
174            self.changes = True
175            if (self.windowTitle() == "PARPG Writing Editor - Untitled"):
176                return
177
178            if (self.open_file_name == None):
179                self.setWindowTitle("PARPG Writing Editor - Untitled")
180                return
181
182            if (self.title_asterisk == False):
183                self.setWindowTitle(self.windowTitle() + " *")
184                self.title_asterisk = True
185           
186    def onTabChanged(self, index):
187        """
188        Check if the tab is the editor or the map viewer and disable/enable actions
189        accordingly
190        @type index: int
191        @param index: The index of the tab
192        @return: None
193        """
194        # it's the main editor
195        if (index == 0):
196            self.dialogMap.clear()
197            self.ui.actionCopy.setEnabled(True)
198            self.ui.actionCut.setEnabled(True)
199            self.ui.actionPaste.setEnabled(True)
200        # it's the dialog map
201        elif (index == 1):
202            self.dialogMap.parser.parse()
203            self.ui.actionCopy.setEnabled(False)
204            self.ui.actionCut.setEnabled(False)
205            self.ui.actionPaste.setEnabled(False)
206        else:
207            print 'Parameter index should be either 0 or 1. Got %d' % index
208
209    def createIcon(self, name):
210        """
211        Creates a QIcon object from the path name
212        @type name: string
213        @param name: the name of the file
214        @rtype: QtGui.QIcon
215        @return: The QIcon object
216        """
217        path = 'data/images/' + name
218        icon = QtGui.QIcon(path)
219        return icon
220
221    def newFile(self):
222        """
223        Start a new file
224        @return: None
225        """
226        self.open_file_name = None
227        self.ui.main_edit.setText("")
228        self.saveEnabled(False)
229
230    def saveFile(self, filename=None):
231        """
232        Save the contents of self.ui.main_edit to filename
233        If filename is None, then open a save dialog
234        @type filename: string
235        @param filename: the file to save to
236        @return: None
237        """
238        # if no filename argument is specified and there is no open file, open the save dialog
239        if (filename == None and self.open_file_name == None):
240            file_dialog = QtGui.QFileDialog(self)
241            file_dialog.setDefaultSuffix("dialog")
242            file_dialog.setNameFilter("Dialog Files (*.dialog)")
243            self.save_file_name = file_dialog.getSaveFileName()
244            self.open_file_name = self.save_file_name
245        # otherwise just save the file
246        else:
247            self.save_file_name = self.open_file_name
248
249        try:
250            text = self.ui.main_edit.toPlainText()
251            codec_file = codecs.open(self.save_file_name, 'w', 'utf-8')
252            codec_file.write(text)
253            codec_file.close()
254            self.saveEnabled(False)
255            last_slash = self.findLastSlash(self.save_file_name)
256            self.setWindowTitle("PARPG Writing Editor - " + self.save_file_name[last_slash+1:])
257            self.title_asterisk = False
258           
259        except IOError:
260            print 'Unable to save to file: %s' % self.save_file_name
261
262    def saveAs(self):
263        """
264        Open a dialog to save the current file as a new file
265        @return: None
266        """
267        self.saveFile()
268
269    def openFile(self, filename=None):
270        """
271        Open a file
272        @type filename: String
273        @param filename: the file to open
274        @return: None
275        """
276        old_file_name = self.open_file_name
277        if (filename == None):
278            file_dialog = QtGui.QFileDialog(self)
279            self.open_file_name = file_dialog.getOpenFileName()
280        else:
281            self.open_file_name = filename
282        try:
283            codec_file = codecs.open(self.open_file_name, 'r', 'utf-8')
284            codec_contents = codec_file.read()
285            self.ui.main_edit.setText(codec_contents)
286            self.saveEnabled(False)
287
288            new_dict = {}
289
290            try:
291                recent_length = len(self.recent_items)
292                keys = self.recent_items.keys()
293                if (recent_length != 0):
294                    keys.remove(keys[recent_length-1])
295                for key in keys:
296                    value = self.recent_items[key]
297                    new_dict[key] = value
298            except:
299                recent_length = 0
300               
301            last_slash = self.findLastSlash(self.open_file_name)
302            before = self.open_file_name[:last_slash+1]
303            after = self.open_file_name[last_slash+1:]
304            new_dict[after] = before
305               
306            self.recent_items = new_dict
307            self.updateRecentItems()
308
309            slash = self.findLastSlash(self.open_file_name)
310            window_title = 'PARPG Writing Editor - ' + self.open_file_name[slash+1:]
311            self.ui.writingEditor.setWindowTitle(window_title)
312            self.title_asterisk = False
313
314        except IOError:
315            print 'Unable to open file: %s' % self.open_file_name
316            self.open_file_name = old_file_name           
317
318    def printFile(self):
319        """
320        Print the currently open file
321        """
322        qprinter = QtGui.QPrinter()
323        print_dialog = PrintDialog(qprinter)
324        ret = print_dialog.run()
325        if (ret == QtGui.QDialog.Accepted):
326            self.ui.main_edit.document().print_(qprinter)
327
328    def saveEnabled(self, value):
329        """
330        Change whether save is enabled
331        @type value: bool
332        @param value: whether to enable or disable save
333        @return: None
334        """
335        self.ui.actionSave.setEnabled(value)
336        self.ui.actionSave_As.setEnabled(value)
337
338    def createAboutWindow(self):
339        """
340        Create the about the program window
341        @return: None
342        """
343        if (not hasattr(self, "about_window")):
344            self.about_window = AboutWindow(self)
345        self.about_window.show()
346
347    def createPrefWindow(self):
348        """
349        Create the preferences window
350        @return: None
351        """
352        if (not hasattr(self, "pref_window")):
353            self.pref_window = PrefWindow(self, self.settings)
354        self.pref_window.show()
355        self.pref_window.button_apply.setEnabled(True)
356
357    def createHelpWindow(self):
358        """
359        Create the help window
360        @return: None
361        """
362        if (not hasattr(self, "help_window")):
363            self.help_window = HelpWindow(self.settings, self)
364        self.help_window.show()
365
366    def getRecentItems(self, filename):
367        """
368        Reads all the filenames from the file filename that contains all the recent files
369        @type filename: string
370        @param filename: the path to the file
371        @return: None
372        """
373        self.recent_items = {}
374        try:
375            recent_files = open(filename, 'r').read().strip()
376           
377            if (recent_files == ""):
378                self.recent_items = None
379                return
380
381            recent_list = recent_files.split('\n')
382
383            for item in recent_list:
384                last_slash = self.findLastSlash(item)                       
385                before = item[:last_slash+1]
386                after = item[last_slash+1:]
387                self.recent_items[after] = before
388
389            self.updateRecentItems()
390            self.ui.menuRecent_Files.removeAction(self.ui.actionNone)
391
392        except IOError:
393            print 'Unable to read the recent files from file: %s\n'\
394                'No recent files will be displayed' % str(filename)
395           
396
397    def updateRecentItems(self):
398        """
399        Make the recent items show up in the gui
400        @return: None
401        """
402        try:
403            self.ui.menuRecent_files.removeAction(self.recent_1)
404        except:
405            print "Cannot remove action self.recent_1"
406        try:
407            self.ui.menuRecent_files.removeAction(self.recent_2)
408        except:
409            print "Cannot remove action self.recent_2"
410        try:
411            self.ui.menuRecent_files.removeAction(self.recent_3)
412        except:
413            print "Cannot remove action self.recent_3"
414        try:
415            self.ui.menuRecent_files.removeAction(self.recent_4)
416        except:
417            print "Cannot remove action self.recent_4"
418
419        recent_keys = []
420        for key in self.recent_items:
421            recent_keys.append(key)
422           
423        try:
424            self.recent_1 = QtGui.QAction(self)
425            self.recent_1.setObjectName(recent_keys[0])
426            self.recent_1.setText(recent_keys[0])
427            self.ui.menuRecent_Files.addAction(self.recent_1)
428            full_path_1 = self.recent_items[recent_keys[0]] + recent_keys[0]
429            QtCore.QObject.connect(self.recent_1, QtCore.SIGNAL('triggered()'),
430                                   lambda: self.openFile(full_path_1))
431           
432        except:
433            print 'Error generating widgets for recent item 1'
434           
435        try:
436            self.recent_2 = QtGui.QAction(self)
437            self.recent_2.setObjectName(recent_keys[1])
438            self.recent_2.setText(recent_keys[1])
439            self.ui.menuRecent_Files.addAction(self.recent_2, 0)
440            full_path_2 = self.recent_items[recent_keys[1]] + recent_keys[1]
441            QtCore.QObject.connect(self.recent_2, QtCore.SIGNAL('triggered()'),
442                                   lambda: self.openFile(full_path_2))
443                   
444        except:
445            print 'Error generating widgets for recent item 2'
446           
447        try:
448            self.recent_3 = QtGui.QAction(self)
449            self.recent_3.setObjectName(recent_keys[2])
450            self.recent_3.setText(recent_keys[2])
451            self.ui.menuRecent_Files.addAction(self.recent_3)
452            full_path_3 = self.recent_items[recent_keys[2]] + recent_keys[2]
453            QtCore.QObject.connect(self.recent_3, QtCore.SIGNAL('triggered()'),
454                                   lambda: self.openFile(full_path_3))
455       
456        except:
457            print 'Error generating widgets for recent item 3'
458
459        try:
460            self.recent_4 = QtGui.QAction(self)
461            self.recent_4.setObjectName(recent_keys[3])
462            self.recent_4.setText(recent_keys[3])
463            self.ui.menuRecent_Files.addAction(self.recent_4)
464            full_path_4 = self.recent_items[recent_keys[3]] + recent_keys[3]
465            QtCore.QObject.connect(self.recent_4, QtCore.SIGNAL('triggered()'),
466                                   lambda: self.openFile(full_path_4))
467       
468        except:
469            print 'Error generating widgets for recent item 4'
470           
471
472    def writeRecentItems(self, filename):
473        """
474        Write the recent items to the file filename
475        @type filename: string
476        @param filename: the file to write to
477        @return: None
478        """
479        if self.recent_items == None:
480            return
481        else:
482            try:
483                file_open = open(filename, 'w')
484                text = ""
485                for key in self.recent_items:
486                    full_path = self.recent_items[key] + key
487                    new_line = full_path + '\n'
488                    text += new_line
489                file_open.write(text)
490                file_open.close()
491                   
492            except IOError:
493                print 'Unable to write the recent files to file: %s\n'\
494                    'No recent files will be written' % str(filename)
495
496    def findLastSlash(self, string):
497        """
498        Find the last slash in string string
499        @type string: string
500        @param string: The string to find the last slash in
501        @return: None
502        """
503        back_num = 1
504        start = len(string)
505        while (True):
506            new_num = start - back_num
507            if (string[new_num] == '/'):
508                last_slash = new_num
509                break
510            else:
511                back_num += 1
512        return last_slash
513
514    def closeEvent(self, event):
515        """
516        Overrides the normal close event so it will ask if you want to save changes etc
517        @type event: QCloseEvent
518        @param event: the event (its provided by the qt system)
519        @return: None
520        """
521        if (self.changes):
522            window = ChangesWindow()
523            ret = window.run()
524            if (ret == QtGui.QMessageBox.Save):
525                self.saveFile()
526                self.writeRecentItems("data/recent_files.txt")
527                event.accept()
528            elif (ret == QtGui.QMessageBox.Discard):
529                self.writeRecentItems("data/recent_files.txt")
530                event.accept()
531            elif (ret == QtGui.QMessageBox.Cancel):
532                event.ignore()
533               
534                       
535    def quit(self, filename):
536        """
537        Quit and then write the recent files to filename and ask about changes
538        @type filename: string
539        @param filename: the file to write to
540        @return: None
541        """
542        self.ui.writingEditor.close()
Note: See TracBrowser for help on using the repository browser.