/*************************************************************************** i/o part of kvoctrain ----------------------------------------------------------------------- begin : Thu Mar 11 20:50:53 MET 1999 copyright : (C) 1999-2001 Ewald Arnold (C) 2001 The KDE-EDU team (C) 2004-2005 Peter Hedlund ----------------------------------------------------------------------- ***************************************************************************/ /*************************************************************************** * * * 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 #include #include #include #include #include #include #include #include #include #include #include "kvoctrain.h" #include "UsageManager.h" #include "common-dialogs/ProgressDlg.h" #include static const char *PATTERN_ALL = I18N_NOOP("*|All Files (*)\n"); static const char *PATTERN_ML = I18N_NOOP("*.kvtml|KVocTrain Markup (*.kvtml)\n"); static const char *PATTERN_LEX = I18N_NOOP("*.lex|Vocabulary Trainer 5.0 (*.lex)\n"); static const char *PATTERN_VL = I18N_NOOP("*.vl|KVoclearn (*.vl)\n"); static const char *PATTERN_TQVO = I18N_NOOP("*.qvo|TQVocab (*.qvo)\n"); static const char *PATTERN_VOC = I18N_NOOP("*.voc|Vokabeltrainer (*.voc)\n"); static const char *PATTERN_CSV = I18N_NOOP("*.csv|Text (*.csv)\n"); static const char *PATTERN_VCB = I18N_NOOP("*.vocab|Vocabbox (*.vocab)\n"); // we can read these #define FILTER_RPATTERN i18n(PATTERN_ML)+i18n(PATTERN_VCB)+i18n(PATTERN_VOC)+i18n(PATTERN_CSV)+i18n(PATTERN_LEX)+i18n(PATTERN_ALL) // we can write these #define FILTER_WPATTERN i18n(PATTERN_ML)+i18n(PATTERN_VCB)+i18n(PATTERN_CSV)+i18n(PATTERN_LEX)+i18n(PATTERN_ALL) void kvoctrainApp::slotTimeOutBackup() { if (Prefs::autoBackup() && doc && doc->isModified() ) { slotStatusMsg(i18n("Autobackup in progress")); slotFileSave(); } if (Prefs::backupTime() > 0) btimer->start(Prefs::backupTime() * 60 * 1000, TRUE); slotStatusMsg(IDS_DEFAULT); } bool kvoctrainApp::queryClose() { bool erg = queryExit(); if (erg) doc->setModified(false); // avoid double query on exit via system menu return erg; } bool kvoctrainApp::queryExit() { saveOptions(); if (!doc || !doc->isModified() ) return true; bool save = (Prefs::autoSave()); //save without asking if (!save) { int exit = KMessageBox::warningYesNoCancel(this, i18n("Vocabulary is modified.\n\nSave file before exit?\n"), kapp->makeStdCaption(""), KStdGuiItem::save(), KStdGuiItem::discard()); if (exit==KMessageBox::Yes) { save = true; // save and exit } else if (exit == KMessageBox::No) { save = false; // dont save but exit } else { return false; // continue work } } if (save) { if (!doc->URL().isEmpty()) slotFileSave(); // save and exit if (doc->isModified()) { // Error while saving or no name slotFileSaveAs(); } } return true; } void kvoctrainApp::slotFileQuit() { /////////////////////////////////////////////////////////////////// // exits the Application if(queryExit()) { doc->setModified(false); // Make sure not to bother about saving again. kapp->quit(); } else slotStatusMsg(IDS_DEFAULT); } void kvoctrainApp::slotProgress(kvoctrainDoc *curr_doc, int percent) { if (pdlg != 0) pdlg->setValue (curr_doc, percent); else if (pbar != 0) pbar->setValue (percent); kapp->processEvents(); } void kvoctrainApp::slotFileOpenRecent(const KURL& url) { slotStatusMsg(i18n("Opening file...")); if (queryExit() && fileOpenRecent->items().count() > 0) { fileOpenRecent->setCurrentItem(-1); loadfileFromPath(url); } slotStatusMsg(IDS_DEFAULT); } void kvoctrainApp::slotFileNew() { slotStatusMsg(i18n("Creating new file...")); if (queryExit() ) { view->setView (0, langset); delete doc; TQString name = ""; doc = new kvoctrainDoc (TQT_TQOBJECT(this), 0 /*KURL(name)*/); loadDocProps(doc); if (doc->numLangs() == 0) { TQString l = "en"; doc->appendLang(l); } view->setView(doc, langset); view->getTable()->setFont(Prefs::tableFont()); view->adjustContent(); connect (doc, TQT_SIGNAL (docModified(bool)), this, TQT_SLOT(slotModifiedDoc(bool))); doc->setModified(false); } slotStatusMsg(IDS_DEFAULT); } void kvoctrainApp::slotFileOpen() { slotStatusMsg(i18n("Opening file...")); if (queryExit() ) { TQString s; KURL url = KFileDialog::getOpenURL(TQString(), FILTER_RPATTERN, parentWidget(), i18n("Open Vocabulary File")); loadfileFromPath(url, true); } slotStatusMsg(IDS_DEFAULT); } void kvoctrainApp::loadfileFromPath(const KURL & url, bool addRecent) { if (!url.path().isEmpty()) { view->setView(0, langset); delete doc; doc = 0; TQString format = i18n("Loading %1"); TQString msg = format.arg(url.path()); slotStatusMsg(msg); prepareProgressBar(); doc = new kvoctrainDoc (TQT_TQOBJECT(this), url); removeProgressBar(); loadDocProps(doc); view->setView(doc, langset); view->getTable()->setFont(Prefs::tableFont()); view->adjustContent(); if (addRecent) fileOpenRecent->addURL(url) /*addRecentFile (url.path())*/; connect (doc, TQT_SIGNAL (docModified(bool)), this, TQT_SLOT(slotModifiedDoc(bool))); doc->setModified(false); } } void kvoctrainApp::slotFileOpenExample() { slotStatusMsg(i18n("Opening example file...")); if (queryExit() ) { TQString s; s = locate("data", "kvoctrain/examples/"); KURL url = KFileDialog::getOpenURL(s, FILTER_RPATTERN, parentWidget(), i18n("Open Example Vocabulary File")); loadfileFromPath(url, false); if (doc) doc->URL().setFileName(TQString()); } slotStatusMsg(IDS_DEFAULT); } void kvoctrainApp::slotGHNS() { if (!m_newStuff) m_newStuff = new KVTNewStuff(this); m_newStuff->download(); } void kvoctrainApp::slotFileMerge() { slotStatusMsg(i18n("Merging file...")); TQString s; KURL url = KFileDialog::getOpenURL(TQString(), FILTER_RPATTERN, parentWidget(), i18n("Merge Vocabulary File")); if (!url.isEmpty() ) { TQString format = i18n("Loading %1"); TQString msg = format.arg(url.path()); slotStatusMsg(msg); prepareProgressBar(); kvoctrainDoc *new_doc = new kvoctrainDoc (TQT_TQOBJECT(this), url); connect (new_doc, TQT_SIGNAL (docModified(bool)), this, TQT_SLOT(slotModifiedDoc(bool))); doc->setModified(false); removeProgressBar(); vector old_names = doc->getLessonDescr(); vector new_names = new_doc->getLessonDescr(); vector old_types = doc->getTypeDescr(); vector new_types = new_doc->getTypeDescr(); vector old_tenses = doc->getTenseDescr(); vector new_tenses = new_doc->getTenseDescr(); vector old_in_query = doc->getLessonsInQuery(); vector new_in_query = new_doc->getLessonsInQuery(); vector old_usages = doc->getUsageDescr(); vector new_usages = new_doc->getUsageDescr(); format = i18n("Merging %1"); msg = format.arg(url.path()); slotStatusMsg(msg); TQApplication::setOverrideCursor( waitCursor ); int lesson_offset = lessons->count()-1; for (int i = 0; i < (int) new_names.size(); i++) { lessons->insertItem (new_names[i]); old_names.push_back(new_names[i]); } doc->setLessonDescr(old_names); for (int i = 0; i < (int) new_in_query.size(); i++) old_in_query.push_back(new_in_query[i]+lesson_offset); doc->setLessonsInQuery(old_in_query); querymanager.setLessonItems(old_in_query); int types_offset = old_types.size(); for (int i = 0; i < (int) new_types.size(); i++) { old_types.push_back(new_types[i]); } doc->setTypeDescr(old_types); QueryManager::setTypeNames(old_types); int tenses_offset = old_tenses.size(); for (int i = 0; i < (int) new_tenses.size(); i++) { old_tenses.push_back(new_tenses[i]); } doc->setTenseDescr(old_tenses); Conjugation::setTenseNames(old_tenses); int usages_offset = old_usages.size(); for (int i = 0; i < (int) new_usages.size(); i++) { old_usages.push_back(new_usages[i]); } doc->setUsageDescr(old_usages); UsageManager::setUsageNames(old_usages); bool equal = true; if (doc->getOriginalIdent() != new_doc->getOriginalIdent()) equal = false; for (int i = 1; i < doc->numLangs(); i++) if (doc->getIdent(i) != new_doc->getIdent(i)) equal = false; if (equal) { // easy way: same language codes, just append for (int i = 0; i < new_doc->numEntries(); i++) { kvoctrainExpr *expr = new_doc->getEntry(i); expr->setLesson(expr->getLesson()+lesson_offset); for (int lang = 0; lang <= (int) expr->numTranslations(); lang++) { TQString t = expr->getType (lang); // adjust type offset if (!t.isEmpty() && t.left(1) == TQM_USER_TYPE) { TQString t2; t.remove (0, 1); t2.setNum (t.toInt()+types_offset); t2.insert (0, TQM_USER_TYPE); expr->setType (lang, t2); } t = expr->getUsageLabel (lang); // adjust usage offset TQString tg; if (!t.isEmpty() ) { TQString t2; while (t.left(strlen(UL_USER_USAGE)) == UL_USER_USAGE) { TQString n; t.remove (0, 1); int next; if ((next = t.find(UL_USAGE_DIV)) >= 0) { n = t.left(next); t.remove (0, next+1); } else { n = t; t = ""; } t2.setNum (n.toInt()+usages_offset); t2.insert (0, UL_USER_USAGE); if (tg.length() == 0) tg = t2; else tg += UL_USAGE_DIV + t2; } if (tg.length() == 0) tg = t; else if (t.length() != 0) tg += UL_USAGE_DIV + t; expr->setUsageLabel (lang, tg); } Conjugation conj = expr->getConjugation(lang); bool condirty = false; for (int ci = 0; ci < conj.numEntries(); ci++) { t = conj.getType(ci); if (!t.isEmpty() && t.left(1) == UL_USER_TENSE) { t.remove (0, strlen(UL_USER_TENSE)); TQString t2; t2.setNum (t.toInt()+tenses_offset); t2.insert (0, UL_USER_TENSE); conj.setType(ci, t2); condirty = true; } if (condirty) expr->setConjugation(lang, conj); } } doc->appendEntry (expr); } doc->setModified(); } else { // hard way: move entries around, most attributes get lost vector move_matrix; vector cs_equal; for (int i = 0; i < TQMAX (doc->numLangs(), new_doc->numLangs()); i++) cs_equal.push_back (false); move_matrix.push_back(new_doc->findIdent(doc->getOriginalIdent())); for (int i = 1; i < doc->numLangs(); i++) move_matrix.push_back(new_doc->findIdent(doc->getIdent(i))); for (int j = 0; j < new_doc->numEntries(); j++) { kvoctrainExpr new_expr; kvoctrainExpr *expr = new_doc->getEntry(j); new_expr.setLesson(expr->getLesson()+lesson_offset); for (int i = 0; i < (int) move_matrix.size(); i++) { int lpos = move_matrix[i]; if (lpos >= 0) { if (lpos == 0) s = expr->getOriginal(); else s = expr->getTranslation(lpos); if (!cs_equal[lpos]) { cs_equal[lpos] = true; TQString id = lpos == 0 ? doc->getOriginalIdent() : doc->getIdent(lpos); } if (i == 0) new_expr.setOriginal(s); else new_expr.setTranslation(i, s); TQString r = expr->getRemark(lpos); new_expr.setRemark (i, r); TQString t = expr->getType(lpos); if (!t.isEmpty() && t.left(1) == TQM_USER_TYPE) { TQString t2; t.remove (0, 1); t2.setNum (t.toInt()+types_offset); t2.insert (0, TQM_USER_TYPE); new_expr.setType (i, t2); } t = expr->getUsageLabel(lpos); if (!t.isEmpty() && t.left(1) == TQM_USER_TYPE) { TQString t2; t.remove (0, 1); t2.setNum (t.toInt()+usages_offset); t2.insert (0, TQM_USER_TYPE); new_expr.setUsageLabel (i, t2); } Conjugation conj = expr->getConjugation(lpos); for (int ci = 0; ci < conj.numEntries(); ci++) { t = conj.getType(ci); if (!t.isEmpty() && t.left(1) == TQM_USER_TYPE) { t.remove (0, strlen(TQM_USER_TYPE)); TQString t2; t2.setNum (t.toInt()+tenses_offset); t2.insert (0, TQM_USER_TYPE); conj.setType(ci, t2); } } } } // only append if entries are used bool used = !new_expr.getOriginal().isEmpty(); for (int i = 1; i < (int) doc->numLangs(); i++) if (!new_expr.getTranslation(i).isEmpty()) used = true; if (used) { doc->appendEntry(&new_expr); doc->setModified(); } } } delete (new_doc); fileOpenRecent->addURL(url); // addRecentFile (url.path()); } view->setView(doc, langset); view->getTable()->setFont(Prefs::tableFont()); view->adjustContent(); TQApplication::restoreOverrideCursor(); slotStatusMsg(IDS_DEFAULT); } void kvoctrainApp::slotFileSave() { if (entryDlg != 0) commitEntryDlg(false); if (doc->URL().fileName() == i18n("Untitled") ) { slotFileSaveAs(); return; } TQString format = i18n("Saving %1"); TQString msg = format.arg(doc->URL().path()); slotStatusMsg(msg); // remove previous backup TQFile::remove(TQFile::encodeName(doc->URL().path()+"~")); ::rename (TQFile::encodeName(doc->URL().path()), TQFile::encodeName(doc->URL().path()+"~")); prepareProgressBar(); saveDocProps(doc); doc->saveAs(TQT_TQOBJECT(this), doc->URL(), doc->getTitle(), kvoctrainDoc::automatic); fileOpenRecent->addURL(doc->URL()); removeProgressBar(); slotStatusMsg(IDS_DEFAULT); } void kvoctrainApp::fillLessonBox(kvoctrainDoc *the_doc) { lessons->clear(); lessons->insertItem (the_doc->getLessonDescr(0)); vector names = the_doc->getLessonDescr(); for (int i = 0; i < (int) names.size(); i++) lessons->insertItem (names[i]); act_lesson = the_doc->getCurrentLesson(); if (act_lesson > lessons->count() ) { act_lesson = 0; the_doc->setCurrentLesson(act_lesson); } lessons->setCurrentItem (act_lesson); } void kvoctrainApp::loadDocProps(kvoctrainDoc *the_doc) { fillLessonBox(the_doc); random_expr1.clear(); random_expr2.clear(); queryList.clear(); the_doc->getQueryLang (act_query_org, act_query_trans); if (!act_query_org.isEmpty() && !act_query_trans.isEmpty() ) { for (int i = 0; i < the_doc->numEntries(); i++) { kvoctrainExpr *entry = the_doc->getEntry(i); if (entry->isInQuery()) { int less = entry->getLesson(); for (int l = (int) queryList.size(); l <= less; l++) { vector ref_vec; queryList.push_back(ref_vec); } QueryEntryRef ref(entry, i); queryList[less].push_back(ref); } } } QueryManager::setTypeNames (doc->getTypeDescr() ); UsageManager::setUsageNames (doc->getUsageDescr() ); Conjugation::setTenseNames (doc->getTenseDescr() ); querymanager.setLessonItems(doc->getLessonsInQuery() ); // remove empty elements for (int i = (int) queryList.size()-1; i >= 0; i--) if (queryList[i].size() == 0) { queryList.erase(queryList.begin() + i); } query_cycle = 1; query_startnum = 0; for (int i = 0; i < (int) queryList.size(); i++) query_startnum += queryList[i].size(); query_num = query_startnum; } void kvoctrainApp::saveDocProps(kvoctrainDoc *the_doc) { the_doc->setQueryLang (act_query_org, act_query_trans); } void kvoctrainApp::slotFileSaveAs() { slotStatusMsg(i18n("Saving file under new filename...")); if (entryDlg != 0) commitEntryDlg(false); KURL url = KFileDialog::getSaveURL(TQString(), FILTER_WPATTERN, parentWidget(), i18n("Save Vocabulary As")); if (!url.isEmpty() ) { TQFileInfo fileinfo(url.path()); if (fileinfo.exists() && KMessageBox::warningContinueCancel(0, i18n("The file
%1
already exists. Do you want to overwrite it?
") .arg(url.path()),TQString(),i18n("Overwrite")) == KMessageBox::Cancel) { // do nothing } else if (doc) { TQString format = i18n("Saving %1"); TQString msg = format.arg(url.path()); slotStatusMsg(msg); TQFile::remove(TQFile::encodeName(url.path()+"~")); // remove previous backup ::rename (TQFile::encodeName(url.path()), TQFile::encodeName(TQString(url.path()+"~"))); saveDocProps(doc); prepareProgressBar(); doc->saveAs(TQT_TQOBJECT(this), url, doc->getTitle(), kvoctrainDoc::automatic); fileOpenRecent->addURL(doc->URL()); removeProgressBar(); } } slotStatusMsg(IDS_DEFAULT); } void kvoctrainApp::slotSaveSelection () { if (entryDlg != 0) commitEntryDlg(false); slotStatusMsg(i18n("Saving selected area under new filename...")); TQString save_separator = Prefs::separator(); Prefs::setSeparator("\t"); kvoctrainDoc seldoc(TQT_TQOBJECT(this), ""); // transfer most important parts seldoc.appendLang(doc->getOriginalIdent()); for (int i = 1; i < doc->numLangs(); i++) seldoc.appendLang(doc->getIdent(i)); seldoc.setAuthor(doc->getAuthor()); seldoc.setLessonDescr(doc->getLessonDescr()); seldoc.setTypeDescr(doc->getTypeDescr()); for (int i = doc->numEntries()-1; i >= 0; i--) if (doc->getEntry(i)->isInQuery() ) seldoc.appendEntry(doc->getEntry(i)); KURL url = KFileDialog::getSaveURL(TQString(), FILTER_WPATTERN, parentWidget(), i18n("Save Vocabulary As")); if (!url.isEmpty() ) { TQFileInfo fileinfo(url.path()); if (fileinfo.exists() && KMessageBox::warningContinueCancel(0, i18n("The file
%1
already exists. Do you want to overwrite it?
") .arg(url.path()),TQString(),i18n("Overwrite")) == KMessageBox::Cancel) { // do nothing } else { TQString format = i18n("Saving %1"); TQString msg = format.arg(url.path()); slotStatusMsg(msg); TQFile::remove(url.path()+"~"); // remove previous backup // FIXME: check error ::rename (TQFile::encodeName(url.path()), TQFile::encodeName(url.path()+"~")); saveDocProps(&seldoc); prepareProgressBar(); seldoc.saveAs(TQT_TQOBJECT(this), url, i18n ("Part of: ") + doc->getTitle(), kvoctrainDoc::automatic); removeProgressBar(); } } Prefs::setSeparator(save_separator); slotStatusMsg(IDS_DEFAULT); } void kvoctrainApp::prepareProgressBar () { statusBar()->clear (); pbar = new KProgress (statusBar()); pbar->setFrameStyle( TQFrame::Panel | TQFrame::Sunken ); statusBar()->addWidget(pbar, 150, true); pbar->show(); } void kvoctrainApp::removeProgressBar () { statusBar()->clear (); statusBar()->removeWidget(pbar); delete pbar; pbar = 0; delete pdlg; pdlg = 0; }