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 | }
|
---|