source: trunk/PARPG/tools/Writing Editor/scripts/writingEditor.py @ 224

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

More updates to the help window

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