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

Revision 217, 20.1 KB checked in by bretzel_parpg, 10 years ago (diff)

This is what I have so far for the writing editor. All the features in it are fully functional except
for the dialog map.
NOTE: You will have to have PyQt4 installed for this application to run. There are some instructions in
the readme but it is incomplete

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