/*************************************************************************** keducabuilder.cpp - description ------------------- begin : Sat May 26 2001 copyright : (C) 2001 by Javier Campos email : javi@asyris.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include "keducabuilder.h" #include "keducabuilder.moc" #include "kcontroladdedit.h" #include "kcontrolheader.h" #include "keducaeditorstartdialog.h" #include "../libkeduca/kgallerydialog.h" #include #include #include #include #include #include #include #include #include #include #include #include static const char* const keducabuilder_data[] = { "15 16 4 1", "a c #0000ff", "# c #008183", "b c #c5c2c5", ". c #ffffff", "...............", ".#############.", ".#...........#.", ".#...aaaa....#.", ".#..aa.baa...#.", ".#......aa...#.", ".#.....aab...#.", ".#....aab....#.", ".#....aab....#.", ".#.....b.....#.", ".#....aa.....#.", ".#....aa.....#.", ".#...........#.", ".#...........#.", ".#############.", "..............."}; KEducaBuilder::KEducaBuilder(TQWidget* parent, const char *name, WFlags f ) : KMainWindow(parent,name,f), _nativeFormat("application/x-edu") { _keducaFile = new FileRead(); initMenuBar(); init(); configRead(); setIcon( KGlobal::iconLoader()->loadIcon("control.png", KIcon::Small) ); _isOpenFile = false; } KEducaBuilder::~KEducaBuilder() { delete _keducaFile; } /** Init graphical interface */ void KEducaBuilder::init() { TQWidget *mainView = new TQWidget(this, "mainview"); TQVBoxLayout *form2Layout = new TQVBoxLayout( mainView ); form2Layout->setSpacing( 2 ); form2Layout->setMargin( 0 ); _split = new TQSplitter( mainView ); _split->setOrientation( Qt::Vertical ); _listAnswer = new KListBox( _split, "_listAnswer" ); _listAnswer->tqsetSizePolicy( TQSizePolicy( (TQSizePolicy::SizeType)7, (TQSizePolicy::SizeType)7, _listAnswer->sizePolicy().hasHeightForWidth() ) ); connect( _listAnswer, TQT_SIGNAL( highlighted(TQListBoxItem *) ), TQT_TQOBJECT(this), TQT_SLOT( slotPreview(TQListBoxItem *) ) ); connect( _listAnswer, TQT_SIGNAL( doubleClicked(TQListBoxItem *) ), TQT_TQOBJECT(this), TQT_SLOT( slotEditbyList(TQListBoxItem *) ) ); _preview = new TQTextView( _split, "_preview" ); _preview->setFrameShape( TQTextView::NoFrame ); _preview->setLineWidth( 1 ); form2Layout->addWidget( _split ); setCentralWidget( mainView ); if (!initialGeometrySet()) resize( TQSize(500, 400).expandedTo(tqminimumSizeHint())); setupGUI( ToolBar | Keys | StatusBar | Create, "keducabuilderui.rc" ); setAutoSaveSettings(); } /** Init menu bar settings */ void KEducaBuilder::initMenuBar() { KStdAction::openNew(TQT_TQOBJECT(this), TQT_SLOT( slotFileOpenNew() ), actionCollection()); KStdAction::open (TQT_TQOBJECT(this), TQT_SLOT( slotFileOpen() ), actionCollection()); (void)new KAction(i18n("Open &Gallery..."), 0, 0, TQT_TQOBJECT(this), TQT_SLOT( slotGallery() ), actionCollection(), "open_gallery"); _recentFiles = KStdAction::openRecent(TQT_TQOBJECT(this), TQT_SLOT ( slotFileOpenURL(const KURL &)), actionCollection()); KStdAction::save (TQT_TQOBJECT(this), TQT_SLOT( slotFileSave() ), actionCollection()); KStdAction::saveAs (TQT_TQOBJECT(this), TQT_SLOT( slotFileSaveAs() ), actionCollection()); KStdAction::print (TQT_TQOBJECT(this), TQT_SLOT( slotFilePrint() ), actionCollection()); (void)new KAction(i18n("Document Info"), "info", 0, TQT_TQOBJECT(this), TQT_SLOT( slotHeader() ), actionCollection(), "info_doc"); KStdAction::quit(TQT_TQOBJECT(this), TQT_SLOT( close() ), actionCollection()); (void)new KAction(i18n("&Add..."), "addquestion", 0, TQT_TQOBJECT(this), TQT_SLOT( slotAdd() ), actionCollection(), "question_add"); (void)new KAction(i18n("&Edit..."), "editquestion", 0, TQT_TQOBJECT(this), TQT_SLOT( slotEdit() ), actionCollection(), "question_edit"); (void)new KAction(i18n("&Remove"), "delquestion", 0, TQT_TQOBJECT(this), TQT_SLOT( slotRemove() ), actionCollection(), "question_remove"); (void)new KAction(i18n("&Up"), "up", 0, TQT_TQOBJECT(this), TQT_SLOT( slotUp() ), actionCollection(), "question_up"); (void)new KAction(i18n("&Down"), "down", 0, TQT_TQOBJECT(this), TQT_SLOT( slotDown() ), actionCollection(), "question_down"); } /** Delete current document and start new */ void KEducaBuilder::slotFileOpenNew() { if (!currentFileMayBeReplaced()) return; if( _keducaFile ) delete _keducaFile; _listAnswer->clear(); _preview->setText("

"+i18n("Welcome To KEduca!")+"

"+ i18n("Add a new Question by using the Edit Menu or by choosing one of the icons above.")+ "
"); _keducaFile = new FileRead(); _isOpenFile = false; // ask for meta information slotHeader(); } /** Open new document. */ void KEducaBuilder::slotFileOpen() { KURL url = KFileDialog::getOpenURL( TQString(), _nativeFormat, this, i18n("Open Educa File") ); if( !url.isEmpty() ) slotFileOpenURL( url ); } /** Open new file */ void KEducaBuilder::slotFileOpenURL( const KURL &url ) { if (!currentFileMayBeReplaced()) return; TQPixmap image0( ( const char** ) keducabuilder_data ); delete _keducaFile; _keducaFile = new FileRead(); if( !_keducaFile->openFile(url) ) { return; } _recentFiles->addURL( url ); _listAnswer->clear(); _isOpenFile = true; _keducaFile->recordFirst(); while( !_keducaFile->recordEOF() ) { _listAnswer->insertItem( image0, _keducaFile->getQuestion( FileRead::TQF_TEXT ) ); _keducaFile->recordNext(); } } /** Item select */ void KEducaBuilder::slotPreview( TQListBoxItem *item ) { // bool match = false; TQString tmpListanswer; // FIND THE SELECT RECORD if( !item ) return; // kdDebug() << "Item : " << _listAnswer->currentItem() <recordAt( _listAnswer->currentItem() ); // START THE PREVIEW VALUES tmpListanswer = "

" + i18n("Answers") + "


"; tmpListanswer += "

"; tmpListanswer +=""; _keducaFile->recordAnswerFirst(); while( !_keducaFile->recordAnswerEOF() ) { tmpListanswer += ""; tmpListanswer += ""; tmpListanswer += ""; _keducaFile->recordAnswerNext(); }; tmpListanswer += "
" : tmpListanswer += "#b84747>"; if( _keducaFile->getQuestionInt( FileRead::TQF_TYPE ) == 3 ) { tmpListanswer += "" + _keducaFile->getAnswer( FileRead::AF_POINT ) + ""; } tmpListanswer += "" : tmpListanswer += "#eadada>"; tmpListanswer += ""+_keducaFile->getAnswer( FileRead::AF_TEXT )+""; tmpListanswer += "
"; if( !_keducaFile->getQuestion( FileRead::TQF_PICTURE ).isEmpty() ) { tmpListanswer += ""; tmpListanswer += "
" + i18n("Question Image") + "
"; tmpListanswer += _keducaFile->getQuestion( FileRead::TQF_PICTURE ) + "
"; }; if( _keducaFile->getQuestionInt( FileRead::TQF_POINTS ) > 0 ) { tmpListanswer += "

" + i18n("Question point") + ": "; tmpListanswer += _keducaFile->getQuestion( FileRead::TQF_POINTS ); } if( _keducaFile->getQuestionInt( FileRead::TQF_TIME ) > 0 ) { tmpListanswer += "

"+i18n("Time")+": "; tmpListanswer += _keducaFile->getQuestion( FileRead::TQF_TIME ); tmpListanswer += i18n(" seconds

"); } if( !_keducaFile->getQuestion( FileRead::TQF_TIP ).isEmpty() ) { tmpListanswer += "

" + i18n("Tip") +": "; tmpListanswer += _keducaFile->getQuestion( FileRead::TQF_TIP ); tmpListanswer += "

"; } if( !_keducaFile->getQuestion( FileRead::TQF_EXPLAIN ).isEmpty() ) { tmpListanswer += "

" + i18n("Explain") + ":" + _keducaFile->getQuestion( FileRead::TQF_EXPLAIN ) + "

"; } _preview->setText( tmpListanswer ); } /** Read config data */ void KEducaBuilder::configRead() { KConfig *config = KGlobal::config(); config->setGroup( "keducacontrol" ); applyMainWindowSettings( config, "keducacontrol" ); _split->setSizes( config->readIntListEntry("Splitter_size") ); _recentFiles->loadEntries(config); } /** Write settings */ void KEducaBuilder::configWrite() { KConfig *config = KGlobal::config(); config->setGroup( "keducacontrol" ); saveMainWindowSettings( config, "keducacontrol" ); config->writeEntry("Splitter_size", _split->sizes() ); _recentFiles->saveEntries(config); config->sync(); } bool KEducaBuilder::currentFileMayBeReplaced() { if (_keducaFile->changed()) { int res = KMessageBox::warningYesNoCancel( widget(), // ask the user to save i18n( "The document \"%1\" has been modified.\n" "Do you want to save it?" ).tqarg( _keducaFile->getCurrentURL().fileName() ), i18n( "Save Document?" ), KStdGuiItem::save(), KStdGuiItem::discard() ); switch (res) { case KMessageBox::Yes: // If the saving was successful, then the file may be replaced return fileSave(); break; case KMessageBox::Cancel: // User cancels operation, do not replace the file return false; break; default: ; } } // file was not changed, it may be replaced return true; } /** Close the window */ bool KEducaBuilder::queryClose () { if (_keducaFile) { if (!currentFileMayBeReplaced()) return false; } configWrite(); return( TRUE ); } /** Add question */ void KEducaBuilder::slotAdd() { TQPixmap image0( ( const char** ) keducabuilder_data ); KControlAddEdit edit(this); edit.init( _keducaFile, false ); if( !edit.exec() ) return; _listAnswer->insertItem( image0, _keducaFile->getQuestion( FileRead::TQF_TEXT ) ); _listAnswer->setCurrentItem( _listAnswer->count()-1 ); slotPreview( _listAnswer->item(_listAnswer->currentItem()) ); } /** Edit question */ void KEducaBuilder::slotEdit() { if( _listAnswer->currentItem() == -1 ) return; TQPixmap image0( ( const char** ) keducabuilder_data ); KControlAddEdit edit(this); edit.init( _keducaFile, true ); if( edit.exec() ) { _listAnswer->changeItem( image0, _keducaFile->getQuestion( FileRead::TQF_TEXT ), _listAnswer->currentItem() ); slotPreview( _listAnswer->item(_listAnswer->currentItem()) ); } } /** Edit question */ void KEducaBuilder::slotRemove() { if( _listAnswer->currentItem() == -1 ) return; _keducaFile->recordDelete(); _listAnswer->removeItem( _listAnswer->currentItem() ); } /** Up record */ void KEducaBuilder::slotUp() { int current = _listAnswer->currentItem(); if( current < 1 ) return; TQPixmap image0( ( const char** ) keducabuilder_data ); _keducaFile->recordSwap( true ); TQString tmpString = _listAnswer->text( current-1 ); _listAnswer->changeItem( image0, _listAnswer->text( current ), current-1 ); _listAnswer->changeItem( image0, tmpString, current ); _listAnswer->setCurrentItem( current-1 ); } /** Down record */ void KEducaBuilder::slotDown() { int current = _listAnswer->currentItem(); if( current == -1 || current == (signed)(_listAnswer->count()-1) ) return; TQPixmap image0( ( const char** ) keducabuilder_data ); _keducaFile->recordSwap( true ); TQString tmpString = _listAnswer->text( current+1 ); _listAnswer->changeItem( image0, _listAnswer->text( current ), current+1 ); _listAnswer->changeItem( image0, tmpString, current ); _listAnswer->setCurrentItem( current+1 ); } /** Save file */ void KEducaBuilder::slotFileSave() { fileSave(); } bool KEducaBuilder::fileSave() { if( !_isOpenFile ) { return fileSaveAs(); } if( checkSave() ) return _keducaFile->saveFile(); return false; } /** Save As... */ void KEducaBuilder::slotFileSaveAs() { fileSaveAs(); } bool KEducaBuilder::fileSaveAs() { if( !checkSave() ) return false; TQCheckBox *saveCompressedCheckBox = new TQCheckBox( i18n( "Compress the file" ), 0 ); saveCompressedCheckBox->setChecked( true ); KFileDialog *dialog=new KFileDialog(TQString(), TQString(), this, "file dialog", true, saveCompressedCheckBox); dialog->setCaption( i18n("Save Document As") ); dialog->setKeepLocation( true ); dialog->setOperationMode( KFileDialog::Saving ); TQStringList mimeFilter(_nativeFormat); dialog->setMimeFilter( mimeFilter, _nativeFormat ); KURL newURL; TQString outputFormat (_nativeFormat); bool bOk; do { bOk=true; if(dialog->exec()==TQDialog::Accepted) { newURL=dialog->selectedURL(); outputFormat=dialog->currentMimeFilter(); } else { bOk = false; break; } kdDebug()<<"Requested saving to file "<property( "X-KDE-NativeExtension" ).toString(); kdDebug() << "KEducaBuilder::slotFileSaveAs outputFormat=" << outputFormat << " extension=" << extension << endl; newURL.setPath( newURL.path() + extension ); } if ( KIO::NetAccess::exists( newURL, false, this ) ) { // this file exists => ask for confirmation bOk = KMessageBox::warningContinueCancel( this, i18n("A document with this name already exists.\n"\ "Do you want to overwrite it?"), i18n("Warning"), i18n("Overwrite") ) == KMessageBox::Continue; } } while ( !bOk ); bool saveCompressed = saveCompressedCheckBox->isChecked(); delete dialog; if (bOk) { bool copyImages = KMessageBox::questionYesNo( this, i18n("If you want to share this document, it is better to copy the images to the same folder as the document.\n"\ "Do you want to copy images?"), i18n("Warning"), i18n("Copy Images"), i18n("Do Not Copy") ) == KMessageBox::Yes; if (_keducaFile->saveFile( newURL, copyImages, saveCompressed ) ) { _recentFiles->addURL(newURL); // we saved the file, so the internal representation is now present as a file _isOpenFile=true; return true; }else { kdDebug()<< "saving of file failed" <getCurrentURL().fileName(); if (file.isEmpty()) file = i18n("Test"); if(printer->setup(this, i18n("Print %1").tqarg(file))) { TQPaintDeviceMetrics metrics(printer); TQPainter p; const int margin=20; int yPos=0; TQString text; p.begin(printer); p.setFont( TQFont(font().family(), 12, TQFont::Bold) ); TQFontMetrics fm = p.fontMetrics(); _keducaFile->recordFirst(); while(!_keducaFile->recordEOF()) { p.drawText( 10, yPos+margin, metrics.width(), fm.lineSpacing(), ExpandTabs | DontClip, _keducaFile->getQuestion(FileRead::TQF_TEXT) ); yPos += fm.lineSpacing(); p.drawLine(10, yPos+margin, metrics.width(), yPos+margin); yPos += 2*fm.lineSpacing(); _keducaFile->recordNext(); } p.end(); } delete printer; } /** Header info */ int KEducaBuilder::slotHeader() { KControlHeader infoDoc(_keducaFile); return infoDoc.exec(); } /** Check if the current document can save */ bool KEducaBuilder::checkSave() { if( _keducaFile->getHeader("title").isEmpty() || _keducaFile->getHeader("category").isEmpty() || _keducaFile->getHeader("type").isEmpty() || _keducaFile->getHeader("level").isEmpty() || _keducaFile->getHeader("language").isEmpty() ) { if (KMessageBox::warningContinueCancel(this, i18n("Unable to save file.\n\nYou must complete the Document Info\n(Only the description is necessary)"), TQString(), i18n("Complete Document Info...")) == KMessageBox::Continue) { if (slotHeader()!=KControlHeader::Accepted) return false; }else return false; } if( _listAnswer->count() < 1 ) { if (KMessageBox::warningContinueCancel(this, i18n("Unable to save file.\n\nYou must insert a question."), TQString(), i18n("Insert Question"))==KMessageBox::Continue) slotAdd(); else return false; } return true; } bool KEducaBuilder::startChooser() { KEducaEditorStartDialog startDialog(this, "KEducaEditorStartDialog", true); switch (startDialog.exec()) { case KEducaEditorStartDialog::OpenDoc: case KEducaEditorStartDialog::OpenRecentDoc: slotFileOpenURL(startDialog.getURL()); break; case KEducaEditorStartDialog::NewDoc: slotFileOpenNew(); break; case KEducaEditorStartDialog::Gallery: initGallery(); break; default: close(); break; } return true; } /** Init Internet Gallery Servers */ void KEducaBuilder::initGallery(const KURL &urlFile) { KGalleryDialog galleries; if( !urlFile.url().isEmpty() ) galleries.putURL( urlFile ); if( galleries.exec() == TQDialog::Accepted ) slotFileOpenURL( galleries.getURL() ); } /** Init Gallery */ void KEducaBuilder::slotGallery() { initGallery(); } /** Double click in list, edit question */ void KEducaBuilder::slotEditbyList(TQListBoxItem *item) { if( item ) slotEdit(); }