/*************************************************************************** * $Id$ ** * Copyright (C) 1992-2000 Trolltech AS. All rights reserved. ** * This file is part of an example program for Qt. This example * program may be used, distributed and modified without limitation. ** ****************************************************************************/ import org.kde.qt.*; import java.util.ArrayList; class Editor extends QWidget { private QMenuBar m; private QMultiLineEdit e; private QPrinter printer = new QPrinter(); private QPopupMenu save_as; private QPopupMenu open_as; private boolean changed; private boolean no_writing = false; static ArrayList codecList = null; static final int Uni = 0; static final int MBug = 1; static final int Lat1 = 2; static final int Local = 3; static final int Guess = 4; static final int Codec = 5; Editor( ) { this(null, null); } Editor( QWidget parent , String name ) { super( parent, name, WDestructiveClose ); m = new QMenuBar( this, "menu" ); QPopupMenu file = new QPopupMenu(this); m.insertItem( "&File", file ); file.insertItem( "&New", this, SLOT("newDoc()"), new QKeySequence(ALT+Key_N) ); file.insertItem( "&Open...", this, SLOT("load()"), new QKeySequence(ALT+Key_O) ); file.insertItem( "&Save...", this, SLOT("save()"), new QKeySequence(ALT+Key_S) ); file.insertSeparator(); open_as = new QPopupMenu(file); file.insertItem( "Open &As", open_as ); save_as = new QPopupMenu(file); file.insertItem( "Sa&ve As", save_as ); file.insertItem( "Add &Encoding", this, SLOT("addEncoding()") ); file.insertSeparator(); file.insertItem( "&Print...", this, SLOT("print()"), new QKeySequence(ALT+Key_P) ); file.insertSeparator(); file.insertItem( "&Close", this, SLOT("close()"),new QKeySequence(ALT+Key_W) ); file.insertItem( "&Quit", qApp(), SLOT("closeAllWindows()"), new QKeySequence(ALT+Key_Q) ); connect( save_as, SIGNAL("activated(int)"), this, SLOT("saveAsEncoding(int)") ); connect( open_as, SIGNAL("activated(int)"), this, SLOT("openAsEncoding(int)") ); rebuildCodecList(); QPopupMenu edit = new QPopupMenu(m); m.insertItem( "&Edit", edit ); edit.insertItem( "To &Uppercase", this, SLOT("toUpper()"), new QKeySequence(ALT+Key_U) ); edit.insertItem( "To &Lowercase", this, SLOT("toLower()"), new QKeySequence(ALT+Key_L) ); edit.insertSeparator(); edit.insertItem( "&Select Font" , this, SLOT("getFont()"), new QKeySequence(ALT+Key_F) ); changed = false; e = new QMultiLineEdit( this, "editor" ); connect( e, SIGNAL(" textChanged()"), this, SLOT(" textChanged()") ); // We use Unifont - if you have it installed you'll see all // Unicode character glyphs. // // Unifont only comes in one pixel size, so we cannot let // it change pixel size as the display DPI changes. // QFont unifont = new QFont("unifont",16,50); unifont.setPixelSize(16); e.setFont( unifont ); e.setFocus(); } public void getFont() { boolean[] ok = { true }; QFont f = QFontDialog.getFont( ok, e.font() ); if ( ok[0] ) { e.setFont( f ); } } void rebuildCodecList() { codecList = new ArrayList(); QTextCodec codec = null; int i; for (i = 0; (codec = QTextCodec.codecForIndex(i)) != null; i++) codecList.add( codec ); int n = codecList.size(); for (int pm=0; pm<2; pm++) { QPopupMenu menu = pm != 0 ? open_as : save_as; menu.clear(); String local = "Local ("; local += QTextCodec.codecForLocale().name(); local += ")"; menu.insertItem( local, Local ); menu.insertItem( "Unicode", Uni ); menu.insertItem( "Latin1", Lat1 ); menu.insertItem( "Microsoft Unicode", MBug ); if ( pm != 0 ) menu.insertItem( "[guess]", Guess ); for ( i = 0; i < n; i++ ) menu.insertItem( ((QTextCodec) codecList.get(i)).name(), Codec + i ); } } void newDoc() { Editor ed = new Editor(); if ( qApp().desktop().size().width() < 450 || qApp().desktop().size().height() < 450 ) { ed.showMaximized(); } else { ed.resize( 400, 400 ); ed.show(); } } void load() { String fn = QFileDialog.getOpenFileName( "", "", this ); if ( fn != null ) load( fn, -1 ); } void load( String fileName ) { load(fileName, -1); } void load( String fileName, int code ) { QFile f = new QFile( fileName ); if ( !f.open( QIODevice.IO_ReadOnly ) ) return; e.setAutoUpdate( false ); QTextStream t = new QTextStream(f); if ( code >= Codec ) t.setCodec( (QTextCodec) codecList.get(code-Codec) ); else if ( code == Uni ) t.setEncoding( QTextStream.Unicode ); else if ( code == MBug ) t.setEncoding( QTextStream.UnicodeReverse ); else if ( code == Lat1 ) t.setEncoding( QTextStream.Latin1 ); else if ( code == Guess ) { f = new QFile(fileName); f.open(QIODevice.IO_ReadOnly); StringBuffer buffer = new StringBuffer(); int l = 256; l=(int)f.readBlock(buffer,l); QTextCodec codec = QTextCodec.codecForContent(buffer.toString(), l); if ( codec != null ) { QMessageBox.information(this,"Encoding","Codec: "+codec.name()); t.setCodec( codec ); } } e.setText( t.read() ); f.close(); e.setAutoUpdate( true ); e.repaint(); setCaption( fileName ); changed = false; } void openAsEncoding( int code ) { //storing filename (proper save) is left as an exercise... String fn = QFileDialog.getOpenFileName( "", "", this ); if ( !fn.equals("") ) load( fn, code ); } boolean save() { //storing filename (proper save) is left as an exercise... String fn = QFileDialog.getSaveFileName( "", "", this ); if ( !fn.equals("") ) return saveAs( fn ); return false; } void saveAsEncoding( int code ) { //storing filename (proper save) is left as an exercise... String fn = QFileDialog.getSaveFileName( "", "", this ); if ( !fn.equals("") ) saveAs( fn, code ); } void addEncoding() { String fn = QFileDialog.getOpenFileName( "", "*.map", this ); if ( !fn.equals("") ) { QFile f = new QFile(fn); if (f.open(QIODevice.IO_ReadOnly)) { if (QTextCodec.loadCharmap(f) != null) { rebuildCodecList(); } else { QMessageBox.warning(null,"Charmap error", "The file did not contain a valid charmap.\n\n" + "A charmap file should look like this:\n" + " thename\n" + " /\n" + " % alias thealias\n" + " CHARMAP\n" + " /x12 \n" + " /xAB/x12 \n" + " ...\n" + " END CHARMAP\n" ); } } } } boolean saveAs( String fileName ) { return saveAs(fileName, -1); } boolean saveAs( String fileName, int code ) { QFile f = new QFile( fileName ); if ( no_writing || !f.open( QIODevice.IO_WriteOnly ) ) { QMessageBox.warning(this,"I/O Error", "The file could not be opened.\n\n" +fileName); return false; } QTextStream t = new QTextStream(f); if ( code >= Codec ) t.setCodec( (QTextCodec) codecList.get(code-Codec) ); else if ( code == Uni ) t.setEncoding( QTextStream.Unicode ); else if ( code == MBug ) t.setEncoding( QTextStream.UnicodeReverse ); else if ( code == Lat1 ) t.setEncoding( QTextStream.Latin1 ); t.writeRawBytes(e.text(), e.text().length()); f.close(); setCaption( fileName ); changed = false; return true; } void print() { if ( printer.setup(this) ) { // opens printer dialog printer.setFullPage(true); // we'll set our own margins QPainter p = new QPainter(); p.begin( printer ); // paint on printer p.setFont( e.font() ); QFontMetrics fm = p.fontMetrics(); QPaintDeviceMetrics metrics = new QPaintDeviceMetrics( printer ); // need width/height // of printer surface int MARGIN = metrics.logicalDpiX() / 2; // half-inch margin int yPos = MARGIN; // y position for each line for( int i = 0 ; i < e.numLines() ; i++ ) { if ( printer.aborted() ) break; if ( yPos + fm.lineSpacing() > metrics.height() - MARGIN ) { // no more room on this page if ( !printer.newPage() ) // start new page break; // some error yPos = MARGIN; // back to top of page } p.drawText( MARGIN, yPos, metrics.width() - 2*MARGIN, fm.lineSpacing(), ExpandTabs, e.textLine( i ) ); yPos += fm.lineSpacing(); } p.end(); // send job to printer } } protected void resizeEvent( QResizeEvent event ) { if ( e != null && m != null ) e.setGeometry( 0, m.height(), width(), height() - m.height() ); } protected void closeEvent( QCloseEvent event ) { event.accept(); if ( changed ) { // the text has been changed switch ( QMessageBox.warning( this, "Qwerty", "Save changes to Document?", tr("&Yes"), tr("&No"), tr("Cancel"), 0, 2) ) { case 0: // yes if ( save() ) event.accept(); else event.ignore(); break; case 1: // no event.accept(); break; default: // cancel event.ignore(); break; } } } void toUpper() { e.setText(e.text().toUpperCase()); } void toLower() { e.setText(e.text().toLowerCase()); } void textChanged() { changed = true; } }