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

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

Fixed some import issues

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.main_edit, QtCore.SIGNAL("textChanged()"),
129                               self.onTextChanged)
130        QtCore.QObject.connect(self.ui.actionNew_File, QtCore.SIGNAL("triggered()"),
131                               self.newFile)
132        QtCore.QObject.connect(self.ui.actionOpen_File, QtCore.SIGNAL("triggered()"),
133                               self.openFile)
134        QtCore.QObject.connect(self.ui.actionSave, QtCore.SIGNAL("triggered()"),
135                               self.saveFile)
136        QtCore.QObject.connect(self.ui.actionPrint, QtCore.SIGNAL("triggered()"),
137                               self.printFile)
138        QtCore.QObject.connect(self.ui.actionExit, QtCore.SIGNAL("triggered()"),
139                               lambda: self.quit('data/recent_files.txt'))
140        QtCore.QObject.connect(self.ui.actionCopy, QtCore.SIGNAL("triggered()"),
141                               self.ui.main_edit.copy)
142        QtCore.QObject.connect(self.ui.actionCut, QtCore.SIGNAL("triggered()"),
143                               self.ui.main_edit.cut)
144        QtCore.QObject.connect(self.ui.actionPaste, QtCore.SIGNAL("triggered()"),
145                               self.ui.main_edit.paste)
146        QtCore.QObject.connect(self.ui.actionPreferences, QtCore.SIGNAL("triggered()"),
147                               self.createPrefWindow)
148        QtCore.QObject.connect(self.ui.actionAbout, QtCore.SIGNAL("triggered()"),
149                               self.createAboutWindow)
150        QtCore.QObject.connect(self.ui.menubar, QtCore.SIGNAL("currentChanged(int)"),
151                               self, QtCore.SIGNAL("enableFunctionsByTabs(int)"))
152        QtCore.QObject.connect(self.ui.actionRedo, QtCore.SIGNAL("triggered()"),
153                               self.ui.main_edit.redo)
154        QtCore.QObject.connect(self.ui.actionUndo, QtCore.SIGNAL("triggered()"),
155                               self.ui.main_edit.undo)
156
157    def onTextChanged(self):
158        """
159        Function called when text is changed
160        """
161        self.saveEnabled(True)
162        if (self.windowTitle() == "PARPG Writing Editor - Untitled"):
163            return
164
165        if (self.open_file_name == None):
166            self.setWindowTitle("PARPG Writing Editor - Untitled")
167            return
168
169        if (self.title_asterisk == False):
170            self.setWindowTitle(self.windowTitle() + " *")
171            self.title_asterisk = True
172
173    def enableFunctionsByTabs(self, index):
174        """
175        Check if the tab is the editor or the map viewer and disable/enable actions
176        accordingly
177        @type index: int
178        @param index: The index of the tab
179        @return: None
180        """
181        if (index == 0):
182            self.ui.actionCopy.setEnabled(True)
183            self.ui.actionCut.setEnabled(True)
184            self.ui.actionPaste.setEnabled(True)
185
186        elif (index == 1):
187            self.ui.actionCopy.setEnabled(False)
188            self.ui.actionCut.setEnabled(False)
189            self.ui.actionPaste.setEnabled(False)
190        else:
191            print 'Parameter index should be either 0 or 1. Got %d' % index
192
193    def createIcon(self, name):
194        """
195        Creates a QIcon object from the path name
196        @type name: string
197        @param name: the name of the file
198        @rtype: QtGui.QIcon
199        @return: The QIcon object
200        """
201        path = 'data/images/' + name
202        icon = QtGui.QIcon(path)
203        return icon
204
205    def newFile(self):
206        """
207        Start a new file
208        @return: None
209        """
210        self.open_file_name = None
211        self.ui.main_edit.setText("")
212        self.saveEnabled(False)
213
214    def saveFile(self, filename=None):
215        """
216        Save the contents of self.ui.main_edit to filename
217        If filename is None, then open a save dialog
218        @type filename: string
219        @param filename: the file to save to
220        @return: None
221        """
222        # if no filename argument is specified and there is no open file, open the save dialog
223        if (filename == None and self.open_file_name == None):
224            file_dialog = QtGui.QFileDialog(self)
225            self.save_file_name = file_dialog.getSaveFileName()
226            self.open_file_name = self.save_file_name
227        # otherwise just save the file
228        else:
229            self.save_file_name = self.open_file_name
230
231        try:
232            text = self.ui.main_edit.toPlainText()
233            codec_file = codecs.open(self.save_file_name, 'w', 'utf-8')
234            codec_file.write(text)
235            codec_file.close()
236            self.saveEnabled(False)
237            last_slash = self.findLastSlash(self.save_file_name)
238            self.setWindowTitle("PARPG Writing Editor - " + self.save_file_name[last_slash+1:])
239            self.title_asterisk = False
240           
241        except IOError:
242            print 'Unable to save to file: %s' % self.save_file_name
243
244    def saveAs(self):
245        """
246        Open a dialog to save the current file as a new file
247        @return: None
248        """
249        self.saveFile()
250
251    def openFile(self, filename=None):
252        """
253        Open a file
254        @type filename: String
255        @param filename: the file to open
256        @return: None
257        """
258        old_file_name = self.open_file_name
259        if (filename == None):
260            file_dialog = QtGui.QFileDialog(self)
261            self.open_file_name = file_dialog.getOpenFileName()
262        else:
263            self.open_file_name = filename
264        try:
265            codec_file = codecs.open(self.open_file_name, 'r', 'utf-8')
266            codec_contents = codec_file.read()
267            self.ui.main_edit.setText(codec_contents)
268            self.saveEnabled(False)
269
270            new_dict = {}
271
272            try:
273                recent_length = len(self.recent_items)
274                keys = self.recent_items.keys()
275                if (recent_length != 0):
276                    keys.remove(keys[recent_length-1])
277                for key in keys:
278                    value = self.recent_items[key]
279                    new_dict[key] = value
280            except:
281                recent_length = 0
282               
283            last_slash = self.findLastSlash(self.open_file_name)
284            before = self.open_file_name[:last_slash+1]
285            after = self.open_file_name[last_slash+1:]
286            new_dict[after] = before
287               
288            self.recent_items = new_dict
289            self.updateRecentItems()
290
291            slash = self.findLastSlash(self.open_file_name)
292            window_title = 'PARPG Writing Editor - ' + self.open_file_name[slash+1:]
293            self.ui.writingEditor.setWindowTitle(window_title)
294            self.title_asterisk = False
295
296        except IOError:
297            print 'Unable to open file: %s' % self.open_file_name
298            self.open_file_name = old_file_name           
299
300    def printFile(self):
301        """
302        Print the currently open file
303        """
304        qprinter = QtGui.QPrinter()
305        print_dialog = PrintDialog(qprinter)
306        ret = print_dialog.run()
307        if (ret == QtGui.QDialog.Accepted):
308            self.ui.main_edit.document().print_(qprinter)
309
310    def saveEnabled(self, value):
311        """
312        Change whether save is enabled
313        @type value: bool
314        @param value: whether to enable or disable save
315        @return: None
316        """
317        self.ui.actionSave.setEnabled(value)
318        self.ui.actionSave_As.setEnabled(value)
319
320    def createAboutWindow(self):
321        """
322        Create the about the program window
323        @return: None
324        """
325        if (not hasattr(self, "about_window")):
326            self.about_window = AboutWindow()
327        self.about_window.show()
328
329    def createPrefWindow(self):
330        """
331        Create the preferences window
332        @return: None
333        """
334        if (not hasattr(self, "pref_window")):
335            self.pref_window = PrefWindow(self, self.settings)
336        self.pref_window.show()
337        self.pref_window.button_apply.setEnabled(True)
338
339    def getRecentItems(self, filename):
340        """
341        Reads all the filenames from the file filename that contains all the recent files
342        @type filename: string
343        @param filename: the path to the file
344        @return: None
345        """
346        self.recent_items = {}
347        try:
348            recent_files = open(filename, 'r').read().strip()
349           
350            if (recent_files == ""):
351                self.recent_items = None
352                return
353
354            recent_list = recent_files.split('\n')
355
356            for item in recent_list:
357                last_slash = self.findLastSlash(item)                       
358                before = item[:last_slash+1]
359                after = item[last_slash+1:]
360                self.recent_items[after] = before
361
362            self.updateRecentItems()
363            self.ui.menuRecent_Files.removeAction(self.ui.actionNone)
364
365        except IOError:
366            print 'Unable to read the recent files from file: %s\n'\
367                'No recent files will be displayed' % str(filename)
368           
369
370    def updateRecentItems(self):
371        """
372        Make the recent items show up in the gui
373        @return: None
374        """
375        try:
376            self.ui.menuRecent_files.removeAction(self.recent_1)
377        except:
378            print "Cannot remove action self.recent_1"
379        try:
380            self.ui.menuRecent_files.removeAction(self.recent_2)
381        except:
382            print "Cannot remove action self.recent_2"
383        try:
384            self.ui.menuRecent_files.removeAction(self.recent_3)
385        except:
386            print "Cannot remove action self.recent_3"
387        try:
388            self.ui.menuRecent_files.removeAction(self.recent_4)
389        except:
390            print "Cannot remove action self.recent_4"
391
392        recent_keys = []
393        for key in self.recent_items:
394            recent_keys.append(key)
395           
396        try:
397            self.recent_1 = QtGui.QAction(self)
398            self.recent_1.setObjectName(recent_keys[0])
399            self.recent_1.setText(recent_keys[0])
400            self.ui.menuRecent_Files.addAction(self.recent_1)
401            full_path_1 = self.recent_items[recent_keys[0]] + recent_keys[0]
402            QtCore.QObject.connect(self.recent_1, QtCore.SIGNAL('triggered()'),
403                                   lambda: self.openFile(full_path_1))
404           
405        except:
406            print 'Error generating widgets for recent item 1'
407           
408        try:
409            self.recent_2 = QtGui.QAction(self)
410            self.recent_2.setObjectName(recent_keys[1])
411            self.recent_2.setText(recent_keys[1])
412            self.ui.menuRecent_Files.addAction(self.recent_2, 0)
413            full_path_2 = self.recent_items[recent_keys[1]] + recent_keys[1]
414            QtCore.QObject.connect(self.recent_2, QtCore.SIGNAL('triggered()'),
415                                   lambda: self.openFile(full_path_2))
416                   
417        except:
418            print 'Error generating widgets for recent item 2'
419           
420        try:
421            self.recent_3 = QtGui.QAction(self)
422            self.recent_3.setObjectName(recent_keys[2])
423            self.recent_3.setText(recent_keys[2])
424            self.ui.menuRecent_Files.addAction(self.recent_3)
425            full_path_3 = self.recent_items[recent_keys[2]] + recent_keys[2]
426            QtCore.QObject.connect(self.recent_3, QtCore.SIGNAL('triggered()'),
427                                   lambda: self.openFile(full_path_3))
428       
429        except:
430            print 'Error generating widgets for recent item 3'
431
432        try:
433            self.recent_4 = QtGui.QAction(self)
434            self.recent_4.setObjectName(recent_keys[3])
435            self.recent_4.setText(recent_keys[3])
436            self.ui.menuRecent_Files.addAction(self.recent_4)
437            full_path_4 = self.recent_items[recent_keys[3]] + recent_keys[3]
438            QtCore.QObject.connect(self.recent_4, QtCore.SIGNAL('triggered()'),
439                                   lambda: self.openFile(full_path_4))
440       
441        except:
442            print 'Error generating widgets for recent item 4'
443           
444
445    def writeRecentItems(self, filename):
446        """
447        Write the recent items to the file filename
448        @type filename: string
449        @param filename: the file to write to
450        @return: None
451        """
452        if self.recent_items == None:
453            return
454        else:
455            try:
456                file_open = open(filename, 'w')
457                text = ""
458                for key in self.recent_items:
459                    full_path = self.recent_items[key] + key
460                    new_line = full_path + '\n'
461                    text += new_line
462                file_open.write(text)
463                file_open.close()
464                   
465            except IOError:
466                print 'Unable to write the recent files to file: %s\n'\
467                    'No recent files will be written' % str(filename)
468
469    def findLastSlash(self, string):
470        """
471        Find the last slash in string string
472        @type string: string
473        @param string: The string to find the last slash in
474        @return: None
475        """
476        back_num = 1
477        start = len(string)
478        while (True):
479            new_num = start - back_num
480            if (string[new_num] == '/'):
481                last_slash = new_num
482                break
483            else:
484                back_num += 1
485        return last_slash
486                       
487    def quit(self, filename):
488        """
489        Quit and then write the recent files to filename and ask about changes
490        @type filename: string
491        @param filename: the file to write to
492        @return: None
493        """
494        # if save is enabled we know there have been changes
495        if (self.ui.actionSave.isEnabled()):
496            window = ChangesWindow()
497            ret = window.run()
498
499            if (ret == QtGui.QMessageBox.Save):
500                self.saveFile()
501                return
502           
503            elif (ret == QtGui.QMessageBox.Discard):
504                self.ui.writingEditor.close()
505                return
506           
507            elif (ret == QtGui.QMessageBox.Cancel):
508                window.close()
509                return
510           
511        self.writeRecentItems(filename)
512        self.ui.writingEditor.close()
Note: See TracBrowser for help on using the repository browser.