[Main Page] [Edit #1] [Edit #2] [Edit #3] [Edit #4] [Edit #5]
In this section we will make the editor a bit more friendly. We'll make the statusbar natter on about the name of the file under hand, have buttons enabled and disabled at will, have the editor ask us whether we really want to lose our work, and, yes, implement the network transparency I mentioned in the previous section.
#!/usr/bin/env python import sys import urllib from kdeui import * from kdecore import * from kfile import * from qt import * # # Constants # TRUE=1 FALSE=0 # Generic command codes ID_OPEN=100 ID_NEW=101 ID_SAVE=102 ID_SAVEAS=103 ID_CLOSE=104 ID_NEWWINDOW=105 ID_CLOSEWINDOW=106 ID_COPY=107 ID_CUT=108 ID_PASTE=109 ID_OPTIONS=110 ID_EXIT=111 ID_HELPCONTENTS=112 ID_ABOUT=113 ID_HINTTEXT=300 # Status item codes EDIT_VERSION_STRING="0.1" # # Edit object # class Edit(KTMainWindow): def __init__ (self): KTMainWindow.__init__(self) self.filename_ = None self.modified_ = FALSE self.initMenuBar() self.initToolBar() self.initStatusBar() self.view=QMultiLineEdit(self, "Main View") self.connect(self.view, SIGNAL("textChanged()"), self.textChanged) self.setView(self.view) self.show() self.enableCommand(ID_OPEN) self.enableCommand(ID_EXIT) self.disableCommand(ID_CLOSE) self.disableCommand(ID_SAVE) self.disableCommand(ID_SAVEAS) def commandCallback (self, id): if id == ID_NEW: self.view.clear() self.filename="" elif id == ID_OPEN: name=KFileDialog.getOpenFileURL() if name is not None: self.load(name) elif id == ID_SAVE: if self.filename_ is not None: self.saveAs(self.filename_) else: name=KFileDialog.getSaveFileName() if name is not None: self.saveAs(name) elif id == ID_SAVEAS: name=KFileDialog.getSaveFileName() if name is not None: self.saveAs(name) elif id == ID_ABOUT: QMessageBox.about(self , "About EditApp" , "This is a simple text editor" ) elif id == ID_EXIT: self.close() def textChanged(self): self.modified_=TRUE; self.enableCommand(ID_SAVE) self.enableCommand(ID_SAVEAS) def initMenuBar(self): self.file=QPopupMenu() self.file.insertItem(i18n("&Open..."), ID_OPEN) self.file.insertItem(i18n("&New..."), ID_NEW) self.file.insertItem(i18n("&Save"), ID_SAVE) self.file.insertItem(i18n("Save &As..."), ID_SAVEAS) self.file.insertSeparator() self.file.insertItem(i18n("&Exit"), ID_EXIT) self.help=QPopupMenu() self.help.insertItem(i18n("&Contents..."), ID_HELPCONTENTS) self.help.insertItem(i18n("&About..."), ID_ABOUT) self.menu=KMenuBar(self) self.menu.insertItem(i18n("&File"), self.file) self.menu.insertItem(i18n("&Help"), self.help) self.menu.show() self.setMenu(self.menu) self.connect(self.file ,SIGNAL("activated(int)") ,self.commandCallback) self.connect(self.help ,SIGNAL("activated(int)") ,self.commandCallback) def initToolBar(self): self.toolbar=KToolBar(self) self.toolbar.insertButton(Icon("filenew.xpm") ,ID_NEW, TRUE ,i18n("Create a new file") ) self.toolbar.insertButton(Icon("fileopen.xpm") ,ID_OPEN, FALSE ,i18n("Open a file") ) self.toolbar.insertButton(Icon("filefloppy.xpm") ,ID_SAVE, FALSE ,i18n("Save the current file") ) self.addToolBar(self.toolbar) self.toolbar.show() self.connect(self.toolbar ,SIGNAL("clicked(int)") ,self.commandCallback ) def initStatusBar(self): self.statusbar=KStatusBar(self) self.statusbar.insertItem("Welcome to Edit",ID_HINTTEXT) self.statusbar.show() self.setStatusBar(self.statusbar) def setHint(self,text): self.statusbar.changeItem(text, ID_HINTTEXT) def closeEvent(self, QCloseEvent): if self.exit()==TRUE: QCloseEvent.accept() def exit(self): die=FALSE if self.modified_==FALSE: die=TRUE else: if QMessageBox.warning ( self , i18n("Unsaved Changes") , "You have unsaved changes, you will loose them \nif you exit now." , 1 , 2 ) == 2: die=FALSE else: die=TRUE return die def enableCommand(self,id): self.toolbar.setItemEnabled(id, TRUE) self.menu.setItemEnabled(id, TRUE) def disableCommand(self,id): self.toolbar.setItemEnabled(id, FALSE) self.menu.setItemEnabled(id, FALSE) def saveAs(self, filename): f=open(filename, "w+") f.write(self.view.text()) self.filename_=filename self.setHint(filename) def load(self, filename): self.view.setText(urllib.urlopen(filename).read()) self.filename_=filename self.setHint(filename) self.modified_=FALSE # # Helper functions # def usage(): print 'edit ' + EDIT_VERSION_STRING + ' (c) Boudewijn Rempt 1999' print 'An adaptation of Richard J. Moores sample application' # # Main clause # if len(sys.argv) > 1: if sys.argv[1] == '-h' or sys.argv[1] == '-help' or sys.argv[1] =='--help': usage() sys.exit() app=KApplication(sys.argv,"EditApp") toplevel=Edit() app.setMainWidget(toplevel) toplevel.show() app.exec_loop()
We have a second state variable, self.modified_, which helps us in remembering whether the user has made a change in his text. Depending on the state of self.modified__, we decide whether to let a warning dialog pop up that asks us about losing our work. That mechanism should be reasonably clear: we connect to the textChanged signal to set the self.modified__ variable to true. Of course, after loading a file, the contents of the editor have changed, but the text itself not, so in the load method we set self.modified_ to false after loading.
In a previous lesson, we said kapp.quit() in the closeEvent. This time we are a bit more sophisticated: we tell pass the event on, saying that we've accepted it: QCloseEvent.accept(). I've been unable to ascertain whether there's any important difference, though.
We also have a nice message appear on standard output when someone starts the editor up with -h, --help or -help from the commandline.
Finally, upon loading, the statusbar text is updated. To do this we need the identifying constant we used to put the initial text in the statusbar.
Maybe it's possible to rewrite the editor so that remote saving becomes possible. The KDE docs don't say it's impossible. Have a go at it, I'd say.
Changes