| 1 | /****************************************************************************
|
|---|
| 2 | ** $Id: qwerty.cpp 2 2005-11-16 15:49:26Z dmik $
|
|---|
| 3 | **
|
|---|
| 4 | ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
|
|---|
| 5 | **
|
|---|
| 6 | ** This file is part of an example program for Qt. This example
|
|---|
| 7 | ** program may be used, distributed and modified without limitation.
|
|---|
| 8 | **
|
|---|
| 9 | *****************************************************************************/
|
|---|
| 10 |
|
|---|
| 11 | #include "qwerty.h"
|
|---|
| 12 | #include <qapplication.h>
|
|---|
| 13 | #include <qfile.h>
|
|---|
| 14 | #include <qfiledialog.h>
|
|---|
| 15 | #include <qpopupmenu.h>
|
|---|
| 16 | #include <qtextstream.h>
|
|---|
| 17 | #include <qpainter.h>
|
|---|
| 18 | #include <qmessagebox.h>
|
|---|
| 19 | #include <qpaintdevicemetrics.h>
|
|---|
| 20 | #include <qptrlist.h>
|
|---|
| 21 | #include <qfontdialog.h>
|
|---|
| 22 |
|
|---|
| 23 | #include <qtextcodec.h>
|
|---|
| 24 |
|
|---|
| 25 | const bool no_writing = FALSE;
|
|---|
| 26 |
|
|---|
| 27 | static QPtrList<QTextCodec> *codecList = 0;
|
|---|
| 28 |
|
|---|
| 29 | enum { Uni = 0, MBug = 1, Lat1 = 2, Local = 3, Guess = 4, Codec = 5 };
|
|---|
| 30 |
|
|---|
| 31 |
|
|---|
| 32 | Editor::Editor( QWidget * parent , const char * name )
|
|---|
| 33 | : QWidget( parent, name, WDestructiveClose )
|
|---|
| 34 | {
|
|---|
| 35 | m = new QMenuBar( this, "menu" );
|
|---|
| 36 |
|
|---|
| 37 | QPopupMenu * file = new QPopupMenu();
|
|---|
| 38 | Q_CHECK_PTR( file );
|
|---|
| 39 | m->insertItem( "&File", file );
|
|---|
| 40 |
|
|---|
| 41 | file->insertItem( "&New", this, SLOT(newDoc()), ALT+Key_N );
|
|---|
| 42 | file->insertItem( "&Open...", this, SLOT(load()), ALT+Key_O );
|
|---|
| 43 | file->insertItem( "&Save...", this, SLOT(save()), ALT+Key_S );
|
|---|
| 44 | file->insertSeparator();
|
|---|
| 45 | open_as = new QPopupMenu();
|
|---|
| 46 | file->insertItem( "Open &As", open_as );
|
|---|
| 47 | save_as = new QPopupMenu();
|
|---|
| 48 | file->insertItem( "Sa&ve As", save_as );
|
|---|
| 49 | file->insertItem( "Add &Encoding", this, SLOT(addEncoding()) );
|
|---|
| 50 | #ifndef QT_NO_PRINTER
|
|---|
| 51 | file->insertSeparator();
|
|---|
| 52 | file->insertItem( "&Print...", this, SLOT(print()), ALT+Key_P );
|
|---|
| 53 | #endif
|
|---|
| 54 | file->insertSeparator();
|
|---|
| 55 | file->insertItem( "&Close", this, SLOT(close()),ALT+Key_W );
|
|---|
| 56 | file->insertItem( "&Quit", qApp, SLOT(closeAllWindows()), ALT+Key_Q );
|
|---|
| 57 |
|
|---|
| 58 | connect( save_as, SIGNAL(activated(int)), this, SLOT(saveAsEncoding(int)) );
|
|---|
| 59 | connect( open_as, SIGNAL(activated(int)), this, SLOT(openAsEncoding(int)) );
|
|---|
| 60 | rebuildCodecList();
|
|---|
| 61 |
|
|---|
| 62 | QPopupMenu * edit = new QPopupMenu();
|
|---|
| 63 | Q_CHECK_PTR( edit );
|
|---|
| 64 | m->insertItem( "&Edit", edit );
|
|---|
| 65 |
|
|---|
| 66 | edit->insertItem( "To &Uppercase", this, SLOT(toUpper()), ALT+Key_U );
|
|---|
| 67 | edit->insertItem( "To &Lowercase", this, SLOT(toLower()), ALT+Key_L );
|
|---|
| 68 | #ifndef QT_NO_FONTDIALOG
|
|---|
| 69 | edit->insertSeparator();
|
|---|
| 70 | edit->insertItem( "&Select Font" , this, SLOT(font()), ALT+Key_T );
|
|---|
| 71 | #endif
|
|---|
| 72 | changed = FALSE;
|
|---|
| 73 | e = new QMultiLineEdit( this, "editor" );
|
|---|
| 74 | connect( e, SIGNAL( textChanged() ), this, SLOT( textChanged() ) );
|
|---|
| 75 |
|
|---|
| 76 | // We use Unifont - if you have it installed you'll see all
|
|---|
| 77 | // Unicode character glyphs.
|
|---|
| 78 | //
|
|---|
| 79 | // Unifont only comes in one pixel size, so we cannot let
|
|---|
| 80 | // it change pixel size as the display DPI changes.
|
|---|
| 81 | //
|
|---|
| 82 | QFont unifont("unifont",16,50); unifont.setPixelSize(16);
|
|---|
| 83 | e->setFont( unifont );
|
|---|
| 84 |
|
|---|
| 85 | e->setFocus();
|
|---|
| 86 | }
|
|---|
| 87 |
|
|---|
| 88 | Editor::~Editor()
|
|---|
| 89 | {
|
|---|
| 90 | }
|
|---|
| 91 |
|
|---|
| 92 | void Editor::font()
|
|---|
| 93 | {
|
|---|
| 94 | #ifndef QT_NO_FONTDIALOG
|
|---|
| 95 | bool ok;
|
|---|
| 96 | QFont f = QFontDialog::getFont( &ok, e->font() );
|
|---|
| 97 | if ( ok ) {
|
|---|
| 98 | e->setFont( f );
|
|---|
| 99 | }
|
|---|
| 100 | #endif
|
|---|
| 101 | }
|
|---|
| 102 |
|
|---|
| 103 |
|
|---|
| 104 |
|
|---|
| 105 | void Editor::rebuildCodecList()
|
|---|
| 106 | {
|
|---|
| 107 | delete codecList;
|
|---|
| 108 | codecList = new QPtrList<QTextCodec>;
|
|---|
| 109 | QTextCodec *codec;
|
|---|
| 110 | int i;
|
|---|
| 111 | for (i = 0; (codec = QTextCodec::codecForIndex(i)); i++)
|
|---|
| 112 | codecList->append( codec );
|
|---|
| 113 | int n = codecList->count();
|
|---|
| 114 | for (int pm=0; pm<2; pm++) {
|
|---|
| 115 | QPopupMenu* menu = pm ? open_as : save_as;
|
|---|
| 116 | menu->clear();
|
|---|
| 117 | QString local = "Local (";
|
|---|
| 118 | local += QTextCodec::codecForLocale()->name();
|
|---|
| 119 | local += ")";
|
|---|
| 120 | menu->insertItem( local, Local );
|
|---|
| 121 | menu->insertItem( "Unicode", Uni );
|
|---|
| 122 | menu->insertItem( "Latin1", Lat1 );
|
|---|
| 123 | menu->insertItem( "Microsoft Unicode", MBug );
|
|---|
| 124 | if ( pm )
|
|---|
| 125 | menu->insertItem( "[guess]", Guess );
|
|---|
| 126 | for ( i = 0; i < n; i++ )
|
|---|
| 127 | menu->insertItem( codecList->at(i)->name(), Codec + i );
|
|---|
| 128 | }
|
|---|
| 129 | }
|
|---|
| 130 |
|
|---|
| 131 | void Editor::newDoc()
|
|---|
| 132 | {
|
|---|
| 133 | Editor *ed = new Editor;
|
|---|
| 134 | if ( qApp->desktop()->size().width() < 450
|
|---|
| 135 | || qApp->desktop()->size().height() < 450 ) {
|
|---|
| 136 | ed->showMaximized();
|
|---|
| 137 | } else {
|
|---|
| 138 | ed->resize( 400, 400 );
|
|---|
| 139 | ed->show();
|
|---|
| 140 | }
|
|---|
| 141 | }
|
|---|
| 142 |
|
|---|
| 143 |
|
|---|
| 144 | void Editor::load()
|
|---|
| 145 | {
|
|---|
| 146 | #ifndef QT_NO_FILEDIALOG
|
|---|
| 147 | QString fn = QFileDialog::getOpenFileName( QString::null, QString::null, this );
|
|---|
| 148 | if ( !fn.isEmpty() )
|
|---|
| 149 | load( fn, -1 );
|
|---|
| 150 | #endif
|
|---|
| 151 | }
|
|---|
| 152 |
|
|---|
| 153 | void Editor::load( const QString& fileName, int code )
|
|---|
| 154 | {
|
|---|
| 155 | QFile f( fileName );
|
|---|
| 156 | if ( !f.open( IO_ReadOnly ) )
|
|---|
| 157 | return;
|
|---|
| 158 |
|
|---|
| 159 | e->setAutoUpdate( FALSE );
|
|---|
| 160 |
|
|---|
| 161 | QTextStream t(&f);
|
|---|
| 162 | if ( code >= Codec )
|
|---|
| 163 | t.setCodec( codecList->at(code-Codec) );
|
|---|
| 164 | else if ( code == Uni )
|
|---|
| 165 | t.setEncoding( QTextStream::Unicode );
|
|---|
| 166 | else if ( code == MBug )
|
|---|
| 167 | t.setEncoding( QTextStream::UnicodeReverse );
|
|---|
| 168 | else if ( code == Lat1 )
|
|---|
| 169 | t.setEncoding( QTextStream::Latin1 );
|
|---|
| 170 | else if ( code == Guess ) {
|
|---|
| 171 | QFile f(fileName);
|
|---|
| 172 | f.open(IO_ReadOnly);
|
|---|
| 173 | char buffer[256];
|
|---|
| 174 | int l = 256;
|
|---|
| 175 | l=f.readBlock(buffer,l);
|
|---|
| 176 | QTextCodec* codec = QTextCodec::codecForContent(buffer, l);
|
|---|
| 177 | if ( codec ) {
|
|---|
| 178 | QMessageBox::information(this,"Encoding",QString("Codec: ")+codec->name());
|
|---|
| 179 | t.setCodec( codec );
|
|---|
| 180 | }
|
|---|
| 181 | }
|
|---|
| 182 | e->setText( t.read() );
|
|---|
| 183 | f.close();
|
|---|
| 184 |
|
|---|
| 185 | e->setAutoUpdate( TRUE );
|
|---|
| 186 | e->repaint();
|
|---|
| 187 | setCaption( fileName );
|
|---|
| 188 |
|
|---|
| 189 | changed = FALSE;
|
|---|
| 190 | }
|
|---|
| 191 |
|
|---|
| 192 | void Editor::openAsEncoding( int code )
|
|---|
| 193 | {
|
|---|
| 194 | #ifndef QT_NO_FILEDIALOG
|
|---|
| 195 | //storing filename (proper save) is left as an exercise...
|
|---|
| 196 | QString fn = QFileDialog::getOpenFileName( QString::null, QString::null, this );
|
|---|
| 197 | if ( !fn.isEmpty() )
|
|---|
| 198 | (void) load( fn, code );
|
|---|
| 199 | #endif
|
|---|
| 200 | }
|
|---|
| 201 |
|
|---|
| 202 | bool Editor::save()
|
|---|
| 203 | {
|
|---|
| 204 | #ifndef QT_NO_FILEDIALOG
|
|---|
| 205 | //storing filename (proper save) is left as an exercise...
|
|---|
| 206 | QString fn = QFileDialog::getSaveFileName( QString::null, QString::null, this );
|
|---|
| 207 | if ( !fn.isEmpty() )
|
|---|
| 208 | return saveAs( fn );
|
|---|
| 209 | return FALSE;
|
|---|
| 210 | #endif
|
|---|
| 211 | }
|
|---|
| 212 |
|
|---|
| 213 | void Editor::saveAsEncoding( int code )
|
|---|
| 214 | {
|
|---|
| 215 | #ifndef QT_NO_FILEDIALOG
|
|---|
| 216 | //storing filename (proper save) is left as an exercise...
|
|---|
| 217 | QString fn = QFileDialog::getSaveFileName( QString::null, QString::null, this );
|
|---|
| 218 | if ( !fn.isEmpty() )
|
|---|
| 219 | (void) saveAs( fn, code );
|
|---|
| 220 | #endif
|
|---|
| 221 | }
|
|---|
| 222 |
|
|---|
| 223 | void Editor::addEncoding()
|
|---|
| 224 | {
|
|---|
| 225 | #ifndef QT_NO_FILEDIALOG
|
|---|
| 226 | QString fn = QFileDialog::getOpenFileName( QString::null, "*.map", this );
|
|---|
| 227 | if ( !fn.isEmpty() ) {
|
|---|
| 228 | QFile f(fn);
|
|---|
| 229 | if (f.open(IO_ReadOnly)) {
|
|---|
| 230 | if (QTextCodec::loadCharmap(&f)) {
|
|---|
| 231 | rebuildCodecList();
|
|---|
| 232 | } else {
|
|---|
| 233 | QMessageBox::warning(0,"Charmap error",
|
|---|
| 234 | "The file did not contain a valid charmap.\n\n"
|
|---|
| 235 | "A charmap file should look like this:\n"
|
|---|
| 236 | " <code_set_name> thename\n"
|
|---|
| 237 | " <escape_char> /\n"
|
|---|
| 238 | " % alias thealias\n"
|
|---|
| 239 | " CHARMAP\n"
|
|---|
| 240 | " <tokenname> /x12 <U3456>\n"
|
|---|
| 241 | " <tokenname> /xAB/x12 <U0023>\n"
|
|---|
| 242 | " ...\n"
|
|---|
| 243 | " END CHARMAP\n"
|
|---|
| 244 | );
|
|---|
| 245 | }
|
|---|
| 246 | }
|
|---|
| 247 | }
|
|---|
| 248 | #endif
|
|---|
| 249 | }
|
|---|
| 250 |
|
|---|
| 251 |
|
|---|
| 252 | bool Editor::saveAs( const QString& fileName, int code )
|
|---|
| 253 | {
|
|---|
| 254 | QFile f( fileName );
|
|---|
| 255 | if ( no_writing || !f.open( IO_WriteOnly ) ) {
|
|---|
| 256 | QMessageBox::warning(this,"I/O Error",
|
|---|
| 257 | QString("The file could not be opened.\n\n")
|
|---|
| 258 | +fileName);
|
|---|
| 259 | return FALSE;
|
|---|
| 260 | }
|
|---|
| 261 | QTextStream t(&f);
|
|---|
| 262 | if ( code >= Codec )
|
|---|
| 263 | t.setCodec( codecList->at(code-Codec) );
|
|---|
| 264 | else if ( code == Uni )
|
|---|
| 265 | t.setEncoding( QTextStream::Unicode );
|
|---|
| 266 | else if ( code == MBug )
|
|---|
| 267 | t.setEncoding( QTextStream::UnicodeReverse );
|
|---|
| 268 | else if ( code == Lat1 )
|
|---|
| 269 | t.setEncoding( QTextStream::Latin1 );
|
|---|
| 270 | t << e->text();
|
|---|
| 271 | f.close();
|
|---|
| 272 | setCaption( fileName );
|
|---|
| 273 | changed = FALSE;
|
|---|
| 274 | return TRUE;
|
|---|
| 275 | }
|
|---|
| 276 |
|
|---|
| 277 | void Editor::print()
|
|---|
| 278 | {
|
|---|
| 279 | #ifndef QT_NO_PRINTER
|
|---|
| 280 | if ( printer.setup(this) ) { // opens printer dialog
|
|---|
| 281 | printer.setFullPage(TRUE); // we'll set our own margins
|
|---|
| 282 | QPainter p;
|
|---|
| 283 | p.begin( &printer ); // paint on printer
|
|---|
| 284 | p.setFont( e->font() );
|
|---|
| 285 | QFontMetrics fm = p.fontMetrics();
|
|---|
| 286 | QPaintDeviceMetrics metrics( &printer ); // need width/height
|
|---|
| 287 | // of printer surface
|
|---|
| 288 | const int MARGIN = metrics.logicalDpiX() / 2; // half-inch margin
|
|---|
| 289 | int yPos = MARGIN; // y position for each line
|
|---|
| 290 |
|
|---|
| 291 | for( int i = 0 ; i < e->numLines() ; i++ ) {
|
|---|
| 292 | if ( printer.aborted() )
|
|---|
| 293 | break;
|
|---|
| 294 | if ( yPos + fm.lineSpacing() > metrics.height() - MARGIN ) {
|
|---|
| 295 | // no more room on this page
|
|---|
| 296 | if ( !printer.newPage() ) // start new page
|
|---|
| 297 | break; // some error
|
|---|
| 298 | yPos = MARGIN; // back to top of page
|
|---|
| 299 | }
|
|---|
| 300 | p.drawText( MARGIN, yPos, metrics.width() - 2*MARGIN,
|
|---|
| 301 | fm.lineSpacing(), ExpandTabs, e->textLine( i ) );
|
|---|
| 302 | yPos += fm.lineSpacing();
|
|---|
| 303 | }
|
|---|
| 304 | p.end(); // send job to printer
|
|---|
| 305 | }
|
|---|
| 306 | #endif
|
|---|
| 307 | }
|
|---|
| 308 |
|
|---|
| 309 | void Editor::resizeEvent( QResizeEvent * )
|
|---|
| 310 | {
|
|---|
| 311 | if ( e && m )
|
|---|
| 312 | e->setGeometry( 0, m->height(), width(), height() - m->height() );
|
|---|
| 313 | }
|
|---|
| 314 |
|
|---|
| 315 | void Editor::closeEvent( QCloseEvent *event )
|
|---|
| 316 | {
|
|---|
| 317 | event->accept();
|
|---|
| 318 |
|
|---|
| 319 | if ( changed ) { // the text has been changed
|
|---|
| 320 | switch ( QMessageBox::warning( this, "Qwerty",
|
|---|
| 321 | "Save changes to Document?",
|
|---|
| 322 | tr("&Yes"),
|
|---|
| 323 | tr("&No"),
|
|---|
| 324 | tr("Cancel"),
|
|---|
| 325 | 0, 2) ) {
|
|---|
| 326 | case 0: // yes
|
|---|
| 327 | if ( save() )
|
|---|
| 328 | event->accept();
|
|---|
| 329 | else
|
|---|
| 330 | event->ignore();
|
|---|
| 331 | break;
|
|---|
| 332 | case 1: // no
|
|---|
| 333 | event->accept();
|
|---|
| 334 | break;
|
|---|
| 335 | default: // cancel
|
|---|
| 336 | event->ignore();
|
|---|
| 337 | break;
|
|---|
| 338 | }
|
|---|
| 339 | }
|
|---|
| 340 | }
|
|---|
| 341 |
|
|---|
| 342 | void Editor::toUpper()
|
|---|
| 343 | {
|
|---|
| 344 | e->setText(e->text().upper());
|
|---|
| 345 | }
|
|---|
| 346 |
|
|---|
| 347 | void Editor::toLower()
|
|---|
| 348 | {
|
|---|
| 349 | e->setText(e->text().lower());
|
|---|
| 350 | }
|
|---|
| 351 |
|
|---|
| 352 | void Editor::textChanged()
|
|---|
| 353 | {
|
|---|
| 354 | changed = TRUE;
|
|---|
| 355 | }
|
|---|