00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "keducabuilder.h"
00019 #include "keducabuilder.moc"
00020
00021 #include "kcontroladdedit.h"
00022 #include "kcontrolheader.h"
00023 #include "keducaeditorstartdialog.h"
00024 #include "../libkeduca/kgallerydialog.h"
00025
00026 #include <kiconloader.h>
00027 #include <klocale.h>
00028 #include <kfiledialog.h>
00029 #include <kedittoolbar.h>
00030 #include <kdebug.h>
00031 #include <kio/netaccess.h>
00032 #include <kmessagebox.h>
00033 #include <kprinter.h>
00034
00035 #include <qlayout.h>
00036 #include <qcheckbox.h>
00037 #include <qpaintdevicemetrics.h>
00038 #include <qpainter.h>
00039
00040 static const char* const keducabuilder_data[] = {
00041 "15 16 4 1",
00042 "a c #0000ff",
00043 "# c #008183",
00044 "b c #c5c2c5",
00045 ". c #ffffff",
00046 "...............",
00047 ".#############.",
00048 ".#...........#.",
00049 ".#...aaaa....#.",
00050 ".#..aa.baa...#.",
00051 ".#......aa...#.",
00052 ".#.....aab...#.",
00053 ".#....aab....#.",
00054 ".#....aab....#.",
00055 ".#.....b.....#.",
00056 ".#....aa.....#.",
00057 ".#....aa.....#.",
00058 ".#...........#.",
00059 ".#...........#.",
00060 ".#############.",
00061 "..............."};
00062
00063 KEducaBuilder::KEducaBuilder(QWidget* parent, const char *name, WFlags f )
00064 : KMainWindow(parent,name,f),
00065 _nativeFormat("application/x-edu")
00066 {
00067 _keducaFile = new FileRead();
00068 initMenuBar();
00069 init();
00070 configRead();
00071 setIcon( KGlobal::iconLoader()->loadIcon("control.png",
00072 KIcon::Small) );
00073 _isOpenFile = false;
00074 }
00075
00076 KEducaBuilder::~KEducaBuilder()
00077 {
00078 delete _keducaFile;
00079 }
00080
00082 void KEducaBuilder::init()
00083 {
00084 QWidget *mainView = new QWidget(this, "mainview");
00085
00086 QVBoxLayout *form2Layout = new QVBoxLayout( mainView );
00087 form2Layout->setSpacing( 2 );
00088 form2Layout->setMargin( 0 );
00089
00090 _split = new QSplitter( mainView );
00091 _split->setOrientation( QSplitter::Vertical );
00092
00093 _listAnswer = new KListBox( _split, "_listAnswer" );
00094 _listAnswer->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)7, _listAnswer->sizePolicy().hasHeightForWidth() ) );
00095 connect( _listAnswer, SIGNAL( highlighted(QListBoxItem *) ), this, SLOT( slotPreview(QListBoxItem *) ) );
00096 connect( _listAnswer, SIGNAL( doubleClicked(QListBoxItem *) ), this, SLOT( slotEditbyList(QListBoxItem *) ) );
00097
00098 _preview = new QTextView( _split, "_preview" );
00099 _preview->setFrameShape( QTextView::NoFrame );
00100 _preview->setLineWidth( 1 );
00101
00102 form2Layout->addWidget( _split );
00103
00104 setCentralWidget( mainView );
00105 if (!initialGeometrySet())
00106 resize( QSize(500, 400).expandedTo(minimumSizeHint()));
00107 setupGUI( ToolBar | Keys | StatusBar | Create, "keducabuilderui.rc" );
00108 setAutoSaveSettings();
00109 }
00110
00112 void KEducaBuilder::initMenuBar()
00113 {
00114 KStdAction::openNew(this, SLOT( slotFileOpenNew() ), actionCollection());
00115 KStdAction::open (this, SLOT( slotFileOpen() ), actionCollection());
00116 (void)new KAction(i18n("Open &Gallery..."), 0, 0, this, SLOT( slotGallery() ), actionCollection(), "open_gallery");
00117 _recentFiles = KStdAction::openRecent(this, SLOT ( slotFileOpenURL(const KURL &)), actionCollection());
00118 KStdAction::save (this, SLOT( slotFileSave() ), actionCollection());
00119 KStdAction::saveAs (this, SLOT( slotFileSaveAs() ), actionCollection());
00120 KStdAction::print (this, SLOT( slotFilePrint() ), actionCollection());
00121 (void)new KAction(i18n("Document Info"), "info", 0, this, SLOT( slotHeader() ), actionCollection(), "info_doc");
00122 KStdAction::quit(this, SLOT( close() ), actionCollection());
00123
00124 (void)new KAction(i18n("&Add..."), "addquestion", 0, this, SLOT( slotAdd() ), actionCollection(), "question_add");
00125 (void)new KAction(i18n("&Edit..."), "editquestion", 0, this, SLOT( slotEdit() ), actionCollection(), "question_edit");
00126 (void)new KAction(i18n("&Remove"), "delquestion", 0, this, SLOT( slotRemove() ), actionCollection(), "question_remove");
00127 (void)new KAction(i18n("&Up"), "up", 0, this, SLOT( slotUp() ), actionCollection(), "question_up");
00128 (void)new KAction(i18n("&Down"), "down", 0, this, SLOT( slotDown() ), actionCollection(), "question_down");
00129 }
00130
00132 void KEducaBuilder::slotFileOpenNew()
00133 {
00134 if (!currentFileMayBeReplaced())
00135 return;
00136
00137 if( _keducaFile ) delete _keducaFile;
00138 _listAnswer->clear();
00139 _preview->setText("<qt><br><center><h1>"+i18n("Welcome To KEduca!")+"</h1>"+
00140 i18n("Add a new Question by using the Edit Menu or by choosing one of the icons above.")+
00141 "</center></qt>");
00142 _keducaFile = new FileRead();
00143 _isOpenFile = false;
00144
00145 slotHeader();
00146 }
00147
00149 void KEducaBuilder::slotFileOpen()
00150 {
00151 KURL url = KFileDialog::getOpenURL( QString::null, _nativeFormat, this, i18n("Open Educa File") );
00152
00153 if( !url.isEmpty() )
00154 slotFileOpenURL( url );
00155 }
00156
00158 void KEducaBuilder::slotFileOpenURL( const KURL &url )
00159 {
00160 if (!currentFileMayBeReplaced())
00161 return;
00162
00163 QPixmap image0( ( const char** ) keducabuilder_data );
00164 delete _keducaFile;
00165 _keducaFile = new FileRead();
00166 if( !_keducaFile->openFile(url) ) { return; }
00167 _recentFiles->addURL( url );
00168 _listAnswer->clear();
00169 _isOpenFile = true;
00170
00171 _keducaFile->recordFirst();
00172 while( !_keducaFile->recordEOF() )
00173 {
00174 _listAnswer->insertItem( image0, _keducaFile->getQuestion( FileRead::QF_TEXT ) );
00175 _keducaFile->recordNext();
00176 }
00177 }
00178
00180 void KEducaBuilder::slotPreview( QListBoxItem *item )
00181 {
00182
00183 QString tmpListanswer;
00184
00185
00186 if( !item ) return;
00187
00188
00189 _keducaFile->recordAt( _listAnswer->currentItem() );
00190
00191
00192 tmpListanswer = "<p><b>" + i18n("Answers") + "</b></p><hr>";
00193 tmpListanswer += "<p>";
00194
00195 tmpListanswer +="<TABLE WIDTH=98%>";
00196 _keducaFile->recordAnswerFirst();
00197 while( !_keducaFile->recordAnswerEOF() )
00198 {
00199 tmpListanswer += "<TR>";
00200 tmpListanswer += "<TD WIDTH=3% BGCOLOR=";
00201 _keducaFile->getAnswerValue() ? tmpListanswer += "#006b6b>" : tmpListanswer += "#b84747>";
00202 if( _keducaFile->getQuestionInt( FileRead::QF_TYPE ) == 3 )
00203 {
00204 tmpListanswer += "<FONT COLOR=#ffffff><b>"
00205 + _keducaFile->getAnswer( FileRead::AF_POINT )
00206 + "</b></FONT>";
00207 }
00208 tmpListanswer += "</TD>";
00209 tmpListanswer += "<TD WIDTH=95% BGCOLOR=";
00210 _keducaFile->getAnswerValue() ? tmpListanswer += "#daeaea>" : tmpListanswer += "#eadada>";
00211 tmpListanswer += "<span style=\"color:black;\">"+_keducaFile->getAnswer( FileRead::AF_TEXT )+"</span>";
00212 tmpListanswer += "</TD></TR>";
00213 _keducaFile->recordAnswerNext();
00214 };
00215 tmpListanswer += "</TABLE>";
00216
00217 if( !_keducaFile->getQuestion( FileRead::QF_PICTURE ).isEmpty() )
00218 {
00219 tmpListanswer += "<table><tr><td><img src=";
00220 tmpListanswer += _keducaFile->getPicture();
00221 tmpListanswer += "></td>";
00222 tmpListanswer += "<td align=right><b>" + i18n("Question Image") + "</b><hr>";
00223 tmpListanswer += _keducaFile->getQuestion( FileRead::QF_PICTURE ) + "</td></tr></table>";
00224 };
00225
00226 if( _keducaFile->getQuestionInt( FileRead::QF_POINTS ) > 0 )
00227 {
00228 tmpListanswer += "<p><b>" + i18n("Question point") + ":</b> ";
00229 tmpListanswer += _keducaFile->getQuestion( FileRead::QF_POINTS );
00230 }
00231
00232 if( _keducaFile->getQuestionInt( FileRead::QF_TIME ) > 0 )
00233 {
00234 tmpListanswer += "<p><b>"+i18n("Time")+":</b> ";
00235 tmpListanswer += _keducaFile->getQuestion( FileRead::QF_TIME );
00236 tmpListanswer += i18n(" seconds</p>");
00237 }
00238
00239 if( !_keducaFile->getQuestion( FileRead::QF_TIP ).isEmpty() )
00240 {
00241 tmpListanswer += "<p><b>" + i18n("Tip") +":</b> ";
00242 tmpListanswer += _keducaFile->getQuestion( FileRead::QF_TIP );
00243 tmpListanswer += "</p>";
00244 }
00245
00246 if( !_keducaFile->getQuestion( FileRead::QF_EXPLAIN ).isEmpty() )
00247 {
00248 tmpListanswer += "<p><b>"
00249 + i18n("Explain") + ":</b>"
00250 + _keducaFile->getQuestion( FileRead::QF_EXPLAIN )
00251 + "</p>";
00252 }
00253
00254 _preview->setText( tmpListanswer );
00255 }
00256
00258 void KEducaBuilder::configRead()
00259 {
00260 KConfig *config = KGlobal::config();
00261
00262 config->setGroup( "keducacontrol" );
00263 applyMainWindowSettings( config, "keducacontrol" );
00264 _split->setSizes( config->readIntListEntry("Splitter_size") );
00265 _recentFiles->loadEntries(config);
00266 }
00267
00269 void KEducaBuilder::configWrite()
00270 {
00271 KConfig *config = KGlobal::config();
00272
00273 config->setGroup( "keducacontrol" );
00274 saveMainWindowSettings( config, "keducacontrol" );
00275 config->writeEntry("Splitter_size", _split->sizes() );
00276 _recentFiles->saveEntries(config);
00277 config->sync();
00278 }
00279
00280 bool KEducaBuilder::currentFileMayBeReplaced()
00281 {
00282 if (_keducaFile->changed())
00283 {
00284 int res = KMessageBox::warningYesNoCancel( widget(),
00285
00286 i18n( "The document \"%1\" has been modified.\n"
00287 "Do you want to save it?" ).arg( _keducaFile->getCurrentURL().fileName() ),
00288 i18n( "Save Document?" ), KStdGuiItem::save(), KStdGuiItem::discard() );
00289 switch (res)
00290 {
00291 case KMessageBox::Yes:
00292
00293 return fileSave();
00294 break;
00295 case KMessageBox::Cancel:
00296
00297 return false;
00298 break;
00299 default: ;
00300 }
00301 }
00302
00303
00304 return true;
00305 }
00306
00308 bool KEducaBuilder::queryClose ()
00309 {
00310 if (_keducaFile) {
00311 if (!currentFileMayBeReplaced())
00312 return false;
00313 }
00314 configWrite();
00315 return( TRUE );
00316 }
00317
00319 void KEducaBuilder::slotAdd()
00320 {
00321 QPixmap image0( ( const char** ) keducabuilder_data );
00322
00323 KControlAddEdit edit(this);
00324 edit.init( _keducaFile, false );
00325 if( !edit.exec() ) return;
00326
00327 _listAnswer->insertItem( image0, _keducaFile->getQuestion( FileRead::QF_TEXT ) );
00328 _listAnswer->setCurrentItem( _listAnswer->count()-1 );
00329 slotPreview( _listAnswer->item(_listAnswer->currentItem()) );
00330 }
00331
00333 void KEducaBuilder::slotEdit()
00334 {
00335 if( _listAnswer->currentItem() == -1 ) return;
00336
00337 QPixmap image0( ( const char** ) keducabuilder_data );
00338
00339 KControlAddEdit edit(this);
00340 edit.init( _keducaFile, true );
00341 if( edit.exec() )
00342 {
00343 _listAnswer->changeItem( image0, _keducaFile->getQuestion( FileRead::QF_TEXT ), _listAnswer->currentItem() );
00344 slotPreview( _listAnswer->item(_listAnswer->currentItem()) );
00345 }
00346 }
00347
00349 void KEducaBuilder::slotRemove()
00350 {
00351 if( _listAnswer->currentItem() == -1 ) return;
00352 _keducaFile->recordDelete();
00353 _listAnswer->removeItem( _listAnswer->currentItem() );
00354 }
00355
00357 void KEducaBuilder::slotUp()
00358 {
00359 int current = _listAnswer->currentItem();
00360
00361 if( current < 1 ) return;
00362 QPixmap image0( ( const char** ) keducabuilder_data );
00363
00364 _keducaFile->recordSwap( true );
00365 QString tmpString = _listAnswer->text( current-1 );
00366 _listAnswer->changeItem( image0, _listAnswer->text( current ), current-1 );
00367 _listAnswer->changeItem( image0, tmpString, current );
00368 _listAnswer->setCurrentItem( current-1 );
00369 }
00370
00372 void KEducaBuilder::slotDown()
00373 {
00374 int current = _listAnswer->currentItem();
00375
00376 if( current == -1 || current == (signed)(_listAnswer->count()-1) ) return;
00377 QPixmap image0( ( const char** ) keducabuilder_data );
00378
00379 _keducaFile->recordSwap( true );
00380 QString tmpString = _listAnswer->text( current+1 );
00381 _listAnswer->changeItem( image0, _listAnswer->text( current ), current+1 );
00382 _listAnswer->changeItem( image0, tmpString, current );
00383 _listAnswer->setCurrentItem( current+1 );
00384 }
00385
00387 void KEducaBuilder::slotFileSave()
00388 {
00389 fileSave();
00390 }
00391 bool KEducaBuilder::fileSave()
00392 {
00393 if( !_isOpenFile ) { return fileSaveAs(); }
00394
00395 if( checkSave() ) return _keducaFile->saveFile();
00396 return false;
00397 }
00398
00400 void KEducaBuilder::slotFileSaveAs()
00401 {
00402 fileSaveAs();
00403 }
00404
00405 bool KEducaBuilder::fileSaveAs()
00406 {
00407 if( !checkSave() ) return false;
00408
00409 QCheckBox *saveCompressedCheckBox = new QCheckBox( i18n( "Compress the file" ), 0 );
00410 saveCompressedCheckBox->setChecked( true );
00411
00412 KFileDialog *dialog=new KFileDialog(QString::null, QString::null, this, "file dialog", true, saveCompressedCheckBox);
00413 dialog->setCaption( i18n("Save Document As") );
00414 dialog->setKeepLocation( true );
00415 dialog->setOperationMode( KFileDialog::Saving );
00416 QStringList mimeFilter(_nativeFormat);
00417 dialog->setMimeFilter( mimeFilter, _nativeFormat );
00418 KURL newURL;
00419 QString outputFormat (_nativeFormat);
00420
00421 bool bOk;
00422 do {
00423 bOk=true;
00424 if(dialog->exec()==QDialog::Accepted) {
00425 newURL=dialog->selectedURL();
00426 outputFormat=dialog->currentMimeFilter();
00427 }
00428 else
00429 {
00430 bOk = false;
00431 break;
00432 }
00433 kdDebug()<<"Requested saving to file "<<newURL.prettyURL() <<endl;
00434 if ( newURL.isEmpty() )
00435 {
00436 bOk = false;
00437 break;
00438 }
00439
00440 if ( QFileInfo( newURL.path() ).extension().isEmpty() ) {
00441
00442 KMimeType::Ptr mime = KMimeType::mimeType( outputFormat );
00443 QString extension = mime->property( "X-KDE-NativeExtension" ).toString();
00444 kdDebug() << "KEducaBuilder::slotFileSaveAs outputFormat=" << outputFormat << " extension=" << extension << endl;
00445 newURL.setPath( newURL.path() + extension );
00446 }
00447
00448 if ( KIO::NetAccess::exists( newURL, false, this ) ) {
00449 bOk = KMessageBox::warningContinueCancel( this,
00450 i18n("A document with this name already exists.\n"\
00451 "Do you want to overwrite it?"),
00452 i18n("Warning"), i18n("Overwrite") ) == KMessageBox::Continue;
00453 }
00454 } while ( !bOk );
00455
00456 bool saveCompressed = saveCompressedCheckBox->isChecked();
00457
00458 delete dialog;
00459
00460 if (bOk) {
00461 bool copyImages = KMessageBox::questionYesNo( this,
00462 i18n("If you want to share this document, it is better to copy the images to the same folder as the document.\n"\
00463 "Do you want to copy images?"),
00464 i18n("Warning"), i18n("Copy Images"), i18n("Do Not Copy") ) == KMessageBox::Yes;
00465 if (_keducaFile->saveFile( newURL, copyImages, saveCompressed ) ) {
00466 _recentFiles->addURL(newURL);
00467
00468 _isOpenFile=true;
00469 return true;
00470 }else {
00471 kdDebug()<< "saving of file failed" <<endl;
00472 return false;
00473 }
00474 }else {
00475 kdDebug()<< "KEducaBuilder: no valid filename selected" <<endl;
00476 return false;
00477 }
00478 }
00479
00481 void KEducaBuilder::slotFilePrint()
00482 {
00483 KPrinter *printer = new KPrinter();
00484
00485 QString file = _keducaFile->getCurrentURL().fileName();
00486 if (file.isEmpty())
00487 file = i18n("Test");
00488 if(printer->setup(this, i18n("Print %1").arg(file)))
00489 {
00490 QPaintDeviceMetrics metrics(printer);
00491 QPainter p;
00492
00493 const int margin=20;
00494 int yPos=0;
00495 QString text;
00496
00497 p.begin(printer);
00498 p.setFont( QFont(font().family(), 12, QFont::Bold) );
00499 QFontMetrics fm = p.fontMetrics();
00500
00501 _keducaFile->recordFirst();
00502 while(!_keducaFile->recordEOF())
00503 {
00504 p.drawText( 10, yPos+margin, metrics.width(), fm.lineSpacing(),
00505 ExpandTabs | DontClip, _keducaFile->getQuestion(FileRead::QF_TEXT) );
00506 yPos += fm.lineSpacing();
00507
00508 p.drawLine(10, yPos+margin, metrics.width(), yPos+margin);
00509 yPos += 2*fm.lineSpacing();
00510
00511 _keducaFile->recordNext();
00512 }
00513
00514 p.end();
00515 }
00516
00517 delete printer;
00518
00519 }
00520
00522 int KEducaBuilder::slotHeader() {
00523 KControlHeader infoDoc(_keducaFile);
00524 return infoDoc.exec();
00525 }
00526
00528 bool KEducaBuilder::checkSave()
00529 {
00530 if( _keducaFile->getHeader("title").isEmpty() ||
00531 _keducaFile->getHeader("category").isEmpty() ||
00532 _keducaFile->getHeader("type").isEmpty() ||
00533 _keducaFile->getHeader("level").isEmpty() ||
00534 _keducaFile->getHeader("language").isEmpty() )
00535 {
00536 if (KMessageBox::warningContinueCancel(this, i18n("Unable to save file.\n\nYou must complete the Document Info\n(Only the description is necessary)"), QString::null, i18n("Complete Document Info..."))
00537 == KMessageBox::Continue) {
00538 if (slotHeader()!=KControlHeader::Accepted)
00539 return false;
00540 }else
00541 return false;
00542 }
00543
00544 if( _listAnswer->count() < 1 )
00545 {
00546 if (KMessageBox::warningContinueCancel(this, i18n("Unable to save file.\n\nYou must insert a question."),
00547 QString::null, i18n("Insert Question"))==KMessageBox::Continue)
00548 slotAdd();
00549 else
00550 return false;
00551 }
00552
00553 return true;
00554 }
00555
00556 bool KEducaBuilder::startChooser() {
00557 KEducaEditorStartDialog startDialog(this, "KEducaEditorStartDialog", true);
00558
00559 switch (startDialog.exec()) {
00560 case KEducaEditorStartDialog::OpenDoc:
00561 case KEducaEditorStartDialog::OpenRecentDoc:
00562 slotFileOpenURL(startDialog.getURL());
00563 break;
00564 case KEducaEditorStartDialog::NewDoc:
00565 slotFileOpenNew();
00566 break;
00567 case KEducaEditorStartDialog::Gallery:
00568 initGallery();
00569 break;
00570 default:
00571 close();
00572 break;
00573 }
00574
00575 return true;
00576 }
00578 void KEducaBuilder::initGallery(const KURL &urlFile)
00579 {
00580 KGalleryDialog galleries;
00581
00582 if( !urlFile.url().isEmpty() )
00583 galleries.putURL( urlFile );
00584
00585 if( galleries.exec() == QDialog::Accepted )
00586 slotFileOpenURL( galleries.getURL() );
00587 }
00588
00590 void KEducaBuilder::slotGallery()
00591 {
00592 initGallery();
00593 }
00594
00596 void KEducaBuilder::slotEditbyList(QListBoxItem *item)
00597 {
00598 if( item )
00599 slotEdit();
00600 }