00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "mainwindow.h"
00023
00024
00025 #include <opie2/odebug.h>
00026 #include <opie2/oresource.h>
00027 #include <qpe/fileselector.h>
00028 #include <qpe/applnk.h>
00029 #include <qpe/fontdatabase.h>
00030 using namespace Opie::Core;
00031
00032
00033 #include "qtextedit.h"
00034 #include <qaction.h>
00035 #include <qtoolbar.h>
00036 #include <qtoolbutton.h>
00037 #include <qtabwidget.h>
00038 #include <qapplication.h>
00039 #include <qfontdatabase.h>
00040 #include <qcombobox.h>
00041 #include <qlineedit.h>
00042 #include <qfileinfo.h>
00043 #include <qfile.h>
00044 #include <qfiledialog.h>
00045 #include <qprinter.h>
00046 #include <qpaintdevicemetrics.h>
00047 #include <qmenubar.h>
00048 #include <qpopupmenu.h>
00049 #include <qcolordialog.h>
00050 #include <qpainter.h>
00051 #include <qstyle.h>
00052
00053 class ButtonMenu : public QToolButton
00054 {
00055 Q_OBJECT
00056 public:
00057 ButtonMenu( QWidget *parent, const char *name=0 )
00058 : QToolButton( parent, name ), current(0)
00059 {
00060 setPopup( new QPopupMenu( this ) );
00061 setPopupDelay( 1 );
00062 connect( popup(), SIGNAL(activated(int)), this, SLOT(selected(int)) );
00063 }
00064
00065 int insertItem(const QIconSet &icon, const QString &text, int id ) {
00066 if ( !popup()->count() ) {
00067 setIconSet( icon );
00068 current = id;
00069 }
00070 return popup()->insertItem( icon, text, id );
00071 }
00072
00073 void setCurrentItem( int id ) {
00074 if ( id != current ) {
00075 current = id;
00076 setIconSet( *popup()->iconSet( id ) );
00077 }
00078 }
00079
00080 virtual QSize sizeHint() const {
00081 return QToolButton::sizeHint() + QSize( 4, 0 );
00082 }
00083
00084 signals:
00085 void activated( int id );
00086
00087 protected slots:
00088 void selected( int id ) {
00089 current = id;
00090 setIconSet( *popup()->iconSet( id ) );
00091 emit activated( id );
00092 }
00093
00094 protected:
00095 virtual void drawButtonLabel( QPainter *p ) {
00096 p->translate( -4, 0 );
00097 QToolButton::drawButtonLabel( p );
00098 p->translate( 4, 0 );
00099 }
00100
00101 private:
00102 int current;
00103 };
00104
00105
00106
00107 MainWindow::MainWindow( QWidget *parent, const char *name, WFlags fl )
00108 : QMainWindow( parent, name, fl ),
00109 doc( 0 )
00110 {
00111 setRightJustification(TRUE);
00112
00113 editorStack = new QWidgetStack( this );
00114
00115 fileSelector = new FileSelector( "text/html",
00116 editorStack, "fileselector" );
00117
00118
00119 fileSelector->setCloseVisible( FALSE );
00120 editorStack->addWidget( fileSelector, 0 );
00121
00122 editor = new Qt3::QTextEdit( editorStack );
00123 editor->setTextFormat( Qt::RichText );
00124 editorStack->addWidget( editor, 1 );
00125
00126 setupActions();
00127
00128 QObject::connect( fileSelector, SIGNAL(closeMe()),
00129 this, SLOT(showEditTools()) );
00130 QObject::connect( fileSelector, SIGNAL(fileSelected(const DocLnk&)),
00131 this, SLOT(openFile(const DocLnk&)) );
00132 QObject::connect( fileSelector, SIGNAL(newSelected(const DocLnk&)),
00133 this, SLOT(newFile(const DocLnk&)) );
00134
00135 if ( fileSelector->fileCount() < 1 )
00136 fileNew();
00137 else {
00138 fileOpen();
00139 }
00140 doConnections( editor );
00141
00142 setCentralWidget( editorStack );
00143 }
00144
00145 MainWindow::~MainWindow()
00146 {
00147 save();
00148 }
00149
00150 void MainWindow::setupActions()
00151 {
00152 setToolBarsMovable(false);
00153
00154 tbMenu = new QToolBar( this );
00155 tbMenu->setHorizontalStretchable( TRUE );
00156
00157 QMenuBar *menu = new QMenuBar( tbMenu );
00158
00159 tbEdit = new QToolBar( this );
00160
00161 QPopupMenu *file = new QPopupMenu( this );
00162 menu->insertItem( tr("File"), file );
00163
00164 QPopupMenu *edit = new QPopupMenu( this );
00165 menu->insertItem( tr("Edit"), edit );
00166
00167
00168
00169 QAction *a;
00170
00171 a = new QAction( tr( "New" ), Opie::Core::OResource::loadPixmap("new", Opie::Core::OResource::SmallIcon),
00172 QString::null, 0, this, 0 );
00173 connect( a, SIGNAL(activated()), this, SLOT(fileNew()) );
00174 a->addTo( file );
00175
00176 a = new QAction( tr( "Open" ), Opie::Core::OResource::loadPixmap( "fileopen", Opie::Core::OResource::SmallIcon ),
00177 QString::null, 0, this, 0 );
00178 connect( a, SIGNAL(activated()), this, SLOT(fileOpen()) );
00179 a->addTo( file );
00180
00181 a = new QAction( tr( "Undo" ), Opie::Core::OResource::loadPixmap("undo", Opie::Core::OResource::SmallIcon),
00182 QString::null, 0, this, "editUndo" );
00183 connect( a, SIGNAL( activated() ), this, SLOT( editUndo() ) );
00184 connect( editor, SIGNAL(undoAvailable(bool)), a, SLOT(setEnabled(bool)) );
00185 a->addTo( tbEdit );
00186 a->addTo( edit );
00187 a = new QAction( tr( "Redo" ), Opie::Core::OResource::loadPixmap("redo", Opie::Core::OResource::SmallIcon),
00188 QString::null, 0, this, "editRedo" );
00189 connect( a, SIGNAL( activated() ), this, SLOT( editRedo() ) );
00190 connect( editor, SIGNAL(redoAvailable(bool)), a, SLOT(setEnabled(bool)) );
00191 a->addTo( tbEdit );
00192 a->addTo( edit );
00193
00194 edit->insertSeparator();
00195
00196 a = new QAction( tr( "Copy" ), Opie::Core::OResource::loadPixmap("copy", Opie::Core::OResource::SmallIcon ),
00197 QString::null, 0, this, "editCopy" );
00198 connect( a, SIGNAL( activated() ), this, SLOT( editCopy() ) );
00199 connect( editor, SIGNAL(copyAvailable(bool)), a, SLOT(setEnabled(bool)) );
00200 a->addTo( tbEdit );
00201 a->addTo( edit );
00202 a = new QAction( tr( "Cut" ), Opie::Core::OResource::loadPixmap("cut", Opie::Core::OResource::SmallIcon ),
00203 QString::null, 0, this, "editCut" );
00204 connect( a, SIGNAL( activated() ), this, SLOT( editCut() ) );
00205 connect( editor, SIGNAL(copyAvailable(bool)), a, SLOT(setEnabled(bool)) );
00206 a->addTo( tbEdit );
00207 a->addTo( edit );
00208 a = new QAction( tr( "Paste" ), Opie::Core::OResource::loadPixmap("paste", Opie::Core::OResource::SmallIcon ),
00209 QString::null, 0, this, "editPaste" );
00210 connect( a, SIGNAL( activated() ), this, SLOT( editPaste() ) );
00211 a->addTo( tbEdit );
00212 a->addTo( edit );
00213
00214 tbFont = new QToolBar( this );
00215 tbFont->setLabel( "Font Actions" );
00216 tbFont->setHorizontalStretchable(TRUE);
00217
00218 comboFont = new QComboBox( FALSE, tbFont );
00219 FontDatabase db;
00220 QStringList f= db.families();
00221 comboFont->insertStringList( db.families() );
00222 connect( comboFont, SIGNAL( activated(const QString&) ),
00223 this, SLOT( textFamily(const QString&) ) );
00224 comboFont->setCurrentItem( comboFont->listBox()->index( comboFont->listBox()->findItem( QApplication::font().family() ) ) );
00225 comboFont->setMaximumWidth(90);
00226
00227 comboSize = new QComboBox( TRUE, tbFont );
00228 QValueList<int> sizes = db.standardSizes();
00229 QValueList<int>::Iterator it = sizes.begin();
00230 for ( ; it != sizes.end(); ++it )
00231 comboSize->insertItem( QString::number( *it ) );
00232 connect( comboSize, SIGNAL( activated(const QString&) ),
00233 this, SLOT( textSize(const QString&) ) );
00234 comboSize->lineEdit()->setText( QString::number( QApplication::font().pointSize() ) );
00235 comboSize->setFixedWidth( 38 );
00236
00237 tbStyle = new QToolBar( this );
00238 tbStyle->setLabel( "Style Actions" );
00239
00240 actionTextBold = new QAction( tr( "Bold" ),
00241 Opie::Core::OResource::loadPixmap("bold", Opie::Core::OResource::SmallIcon ),
00242 QString::null, CTRL + Key_B,
00243 this, "textBold" );
00244 connect( actionTextBold, SIGNAL( activated() ), this, SLOT( textBold() ) );
00245 actionTextBold->addTo( tbStyle );
00246 actionTextBold->setToggleAction( TRUE );
00247 actionTextItalic = new QAction( tr( "Italic" ),
00248 Opie::Core::OResource::loadPixmap("italic", Opie::Core::OResource::SmallIcon ),
00249 tr( "&Italic" ), CTRL + Key_I,
00250 this, "textItalic" );
00251 connect( actionTextItalic, SIGNAL( activated() ), this,
00252 SLOT( textItalic() ) );
00253 actionTextItalic->addTo( tbStyle );
00254 actionTextItalic->setToggleAction( TRUE );
00255 actionTextUnderline = new QAction( tr( "Underline" ),
00256 Opie::Core::OResource::loadPixmap("underline", Opie::Core::OResource::SmallIcon ),
00257 tr( "&Underline" ), CTRL + Key_U,
00258 this, "textUnderline" );
00259 connect( actionTextUnderline, SIGNAL( activated() ),
00260 this, SLOT( textUnderline() ) );
00261 actionTextUnderline->addTo( tbStyle );
00262 actionTextUnderline->setToggleAction( TRUE );
00263
00264 alignMenu = new ButtonMenu( tbStyle );
00265 alignMenu->insertItem( Opie::Core::OResource::loadPixmap("left", Opie::Core::OResource::SmallIcon), tr("Left"), AlignLeft );
00266 alignMenu->insertItem( Opie::Core::OResource::loadPixmap("center", Opie::Core::OResource::SmallIcon),
00267 tr("Center"), AlignCenter );
00268 alignMenu->insertItem( Opie::Core::OResource::loadPixmap("right", Opie::Core::OResource::SmallIcon),
00269 tr("Right"), AlignRight );
00270 alignMenu->insertItem( Opie::Core::OResource::loadPixmap("opie-write/justify", Opie::Core::OResource::SmallIcon),
00271 tr("Full"), Qt3::AlignJustify );
00272 connect( alignMenu, SIGNAL(activated(int)), this, SLOT(textAlign(int)) );
00273 }
00274
00275 Qt3::QTextEdit *MainWindow::currentEditor() const
00276 {
00277 return editor;
00278 }
00279
00280 void MainWindow::doConnections( Qt3::QTextEdit *e )
00281 {
00282 connect( e, SIGNAL( currentFontChanged(const QFont&) ),
00283 this, SLOT( fontChanged(const QFont&) ) );
00284 connect( e, SIGNAL( currentColorChanged(const QColor&) ),
00285 this, SLOT( colorChanged(const QColor&) ) );
00286 connect( e, SIGNAL( currentAlignmentChanged(int) ),
00287 this, SLOT( alignmentChanged(int) ) );
00288 }
00289
00290 void MainWindow::updateFontSizeCombo( const QFont &f )
00291 {
00292 comboSize->clear();
00293 FontDatabase fdb;
00294 QValueList<int> sizes = fdb.pointSizes( f.family() );
00295 QValueList<int>::Iterator it = sizes.begin();
00296 for ( ; it != sizes.end(); ++it )
00297 comboSize->insertItem( QString::number( *it ) );
00298 }
00299
00300 void MainWindow::editUndo()
00301 {
00302 if ( !currentEditor() )
00303 return;
00304 currentEditor()->undo();
00305 }
00306
00307 void MainWindow::editRedo()
00308 {
00309 if ( !currentEditor() )
00310 return;
00311 currentEditor()->redo();
00312 }
00313
00314 void MainWindow::editCut()
00315 {
00316 if ( !currentEditor() )
00317 return;
00318 currentEditor()->cut();
00319 }
00320
00321 void MainWindow::editCopy()
00322 {
00323 if ( !currentEditor() )
00324 return;
00325 currentEditor()->copy();
00326 }
00327
00328 void MainWindow::editPaste()
00329 {
00330 if ( !currentEditor() )
00331 return;
00332 currentEditor()->paste();
00333 }
00334
00335 void MainWindow::textBold()
00336 {
00337 if ( !currentEditor() )
00338 return;
00339 currentEditor()->setBold( actionTextBold->isOn() );
00340 }
00341
00342 void MainWindow::textUnderline()
00343 {
00344 if ( !currentEditor() )
00345 return;
00346 currentEditor()->setUnderline( actionTextUnderline->isOn() );
00347 }
00348
00349 void MainWindow::textItalic()
00350 {
00351 if ( !currentEditor() )
00352 return;
00353 currentEditor()->setItalic( actionTextItalic->isOn() );
00354 }
00355
00356 void MainWindow::textFamily( const QString &f )
00357 {
00358 if ( !currentEditor() )
00359 return;
00360 currentEditor()->setFamily( f );
00361 currentEditor()->viewport()->setFocus();
00362 }
00363
00364 void MainWindow::textSize( const QString &p )
00365 {
00366 if ( !currentEditor() )
00367 return;
00368 currentEditor()->setPointSize( p.toInt() );
00369 currentEditor()->viewport()->setFocus();
00370 }
00371
00372 void MainWindow::textStyle( int i )
00373 {
00374 if ( !currentEditor() )
00375 return;
00376 if ( i == 0 )
00377 currentEditor()->setParagType( Qt3::QStyleSheetItem::DisplayBlock,
00378 Qt3::QStyleSheetItem::ListDisc );
00379 else if ( i == 1 )
00380 currentEditor()->setParagType( Qt3::QStyleSheetItem::DisplayListItem,
00381 Qt3::QStyleSheetItem::ListDisc );
00382 else if ( i == 2 )
00383 currentEditor()->setParagType( Qt3::QStyleSheetItem::DisplayListItem,
00384 Qt3::QStyleSheetItem::ListCircle );
00385 else if ( i == 3 )
00386 currentEditor()->setParagType( Qt3::QStyleSheetItem::DisplayListItem,
00387 Qt3::QStyleSheetItem::ListSquare );
00388 else if ( i == 4 )
00389 currentEditor()->setParagType( Qt3::QStyleSheetItem::DisplayListItem,
00390 Qt3::QStyleSheetItem::ListDecimal );
00391 else if ( i == 5 )
00392 currentEditor()->setParagType( Qt3::QStyleSheetItem::DisplayListItem,
00393 Qt3::QStyleSheetItem::ListLowerAlpha );
00394 else if ( i == 6 )
00395 currentEditor()->setParagType( Qt3::QStyleSheetItem::DisplayListItem,
00396 Qt3::QStyleSheetItem::ListUpperAlpha );
00397 currentEditor()->viewport()->setFocus();
00398 }
00399
00400 void MainWindow::textAlign( int a )
00401 {
00402 if ( !currentEditor() )
00403 return;
00404 editor->setAlignment( a );
00405 }
00406
00407 void MainWindow::fontChanged( const QFont &f )
00408 {
00409 comboFont->setCurrentItem( comboFont->listBox()->index( comboFont->listBox()->findItem( f.family() ) ) );
00410 updateFontSizeCombo( f );
00411 comboSize->lineEdit()->setText( QString::number( f.pointSize() ) );
00412 actionTextBold->setOn( f.bold() );
00413 actionTextItalic->setOn( f.italic() );
00414 actionTextUnderline->setOn( f.underline() );
00415 }
00416
00417 void MainWindow::colorChanged( const QColor & )
00418 {
00419 }
00420
00421 void MainWindow::alignmentChanged( int a )
00422 {
00423 if ( ( a == Qt3::AlignAuto ) || ( a & AlignLeft )) {
00424 alignMenu->setCurrentItem(AlignLeft);
00425 } else if ( ( a & AlignCenter ) ) {
00426 alignMenu->setCurrentItem(AlignCenter);
00427 } else if ( ( a & AlignRight ) ) {
00428 alignMenu->setCurrentItem(AlignRight);
00429 } else if ( ( a & Qt3::AlignJustify ) ) {
00430 alignMenu->setCurrentItem(Qt3::AlignJustify);
00431 }
00432 }
00433
00434 void MainWindow::editorChanged( QWidget * )
00435 {
00436 if ( !currentEditor() )
00437 return;
00438 fontChanged( currentEditor()->font() );
00439 colorChanged( currentEditor()->color() );
00440 alignmentChanged( currentEditor()->alignment() );
00441 }
00442
00443 void MainWindow::fileOpen()
00444 {
00445 save();
00446 editorStack->raiseWidget( fileSelector );
00447 fileSelector->reread();
00448 hideEditTools();
00449 fileSelector->setNewVisible( TRUE );
00450 clear();
00451 updateCaption();
00452 }
00453
00454 void MainWindow::fileRevert()
00455 {
00456 odebug << "QMainWindow::fileRevert needs to be done" << oendl;
00457 }
00458
00459 void MainWindow::fileNew()
00460 {
00461 editor->setTextFormat( Qt::RichText );
00462 save();
00463 newFile(DocLnk());
00464 }
00465
00466 void MainWindow::insertTable()
00467 {
00468 odebug << "MainWindow::insertTable() needs to be done" << oendl;
00469 }
00470
00471 void MainWindow::newFile( const DocLnk &dl )
00472 {
00473 DocLnk nf = dl;
00474 nf.setType( "text/html" );
00475 clear();
00476 editorStack->raiseWidget( editor );
00477 editor->viewport()->setFocus();
00478 doc = new DocLnk( nf );
00479 updateCaption();
00480 }
00481
00482 void MainWindow::openFile( const DocLnk &dl )
00483 {
00484 FileManager fm;
00485 QString txt;
00486 if ( !fm.loadFile( dl, txt ) )
00487 odebug << "couldn't open file" << oendl;
00488 clear();
00489 editorStack->raiseWidget( editor );
00490 editor->viewport()->setFocus();
00491 doc = new DocLnk( dl );
00492 editor->setText( txt );
00493 editor->setModified( FALSE );
00494 updateCaption();
00495 }
00496
00497 void MainWindow::showEditTools( void )
00498 {
00499 tbMenu->show();
00500 tbEdit->show();
00501 tbFont->show();
00502 tbStyle->show();
00503 }
00504
00505 void MainWindow::hideEditTools( void )
00506 {
00507
00508 actionTextBold->setOn( FALSE );
00509 actionTextItalic->setOn( FALSE );
00510 actionTextUnderline->setOn( FALSE );
00511
00512 comboSize->lineEdit()->setText( QString::number(QApplication::font().pointSize() ) );
00513 tbMenu->hide();
00514 tbEdit->hide();
00515 tbFont->hide();
00516 tbStyle->hide();
00517 }
00518
00519
00520 void MainWindow::save()
00521 {
00522 if ( !doc )
00523 return;
00524 if ( !editor->isModified() )
00525 return;
00526
00527 QString rt = editor->text();
00528
00529
00530 editor->setTextFormat( Qt::PlainText );
00531 QString pt = editor->text();
00532 editor->setTextFormat( Qt::RichText );
00533
00534 if ( doc->name().isEmpty() ) {
00535 unsigned ispace = pt.find( ' ' );
00536 unsigned ienter = pt.find( '\n' );
00537 int i = (ispace < ienter) ? ispace : ienter;
00538 QString docname;
00539 if ( i == -1 ) {
00540 if ( pt.isEmpty() )
00541 docname = "Empty Text";
00542 else
00543 docname = pt;
00544 } else {
00545 docname = pt.left( i );
00546 }
00547 doc->setName(docname);
00548 }
00549 FileManager fm;
00550 fm.saveFile( *doc, rt );
00551 }
00552
00553 void MainWindow::clear()
00554 {
00555 delete doc;
00556 doc = 0;
00557 editor->clear();
00558 }
00559
00560 void MainWindow::updateCaption()
00561 {
00562 if ( !doc )
00563 setCaption( tr("Rich Text Editor") );
00564 else {
00565 QString s = doc->name();
00566 if ( s.isEmpty() )
00567 s = tr( "Unnamed" );
00568 setCaption( s + " - " + tr("Rich Text Editor") );
00569 }
00570 }
00571
00572 void MainWindow::closeEvent( QCloseEvent *e )
00573 {
00574 if ( editorStack->visibleWidget() == editor ) {
00575
00576 fileOpen();
00577 e->ignore();
00578 } else {
00579 e->accept();
00580 }
00581 }
00582
00583 #include "mainwindow.moc"