diff --git a/CMakeLists.txt b/CMakeLists.txt index 291a69f..10101f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,44 +1,44 @@ project(LibKEduVocDocument) cmake_minimum_required(VERSION 3.5) find_package(ECM 1.3.0 REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) find_package(Qt5 5.2 REQUIRED NO_MODULE COMPONENTS Xml Gui Widgets DBus Core Multimedia) -find_package(KF5 5.3.0 REQUIRED COMPONENTS I18n Archive KIO Completion Sonnet Notifications XmlGui Kross ) +find_package(KF5 5.3.0 REQUIRED COMPONENTS I18n Archive KIO Completion Sonnet Notifications XmlGui Kross NewStuff ) #add_definitions( -Wall -fprofile-arcs -ftest-coverage ) include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ) remove_definitions(-DQT_NO_CAST_FROM_ASCII) remove_definitions(-DQT_NO_CAST_FROM_BYTEARRAY) remove_definitions(-DQT_NO_KEYWORDS) add_definitions(-DQT_NO_CAST_TO_ASCII) add_definitions(-DQT_NO_URL_CAST_FROM_STRING) add_definitions(-DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS) add_definitions(-DTRANSLATION_DOMAIN=\"libkeduvocdocument\") add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x060000) include(KDEInstallDirs) include(KDECompilerSettings NO_POLICY_SCOPE) include(KDECMakeSettings) include(GenerateExportHeader) add_subdirectory(keduvocdocument) configure_file( "${LibKEduVocDocument_SOURCE_DIR}/LibKEduVocDocumentConfig.cmake.in" "${LibKEduVocDocument_BINARY_DIR}/LibKEduVocDocumentConfig.cmake" @ONLY ) set(_LibKEduVocDocument_CONFIG_DEST "${LIB_INSTALL_DIR}/cmake/libkeduvocdocument") install( FILES "${LibKEduVocDocument_BINARY_DIR}/LibKEduVocDocumentConfig.cmake" DESTINATION "${_LibKEduVocDocument_CONFIG_DEST}" ) install( EXPORT LibKEduVocDocumentTargets DESTINATION "${_LibKEduVocDocument_CONFIG_DEST}" NAMESPACE LibKEduVocDocumentImport__ FILE LibKEduVocDocumentTargets.cmake ) feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/keduvocdocument/CMakeLists.txt b/keduvocdocument/CMakeLists.txt index 380fd0c..94c064c 100644 --- a/keduvocdocument/CMakeLists.txt +++ b/keduvocdocument/CMakeLists.txt @@ -1,237 +1,241 @@ if (BUILD_TESTING) add_subdirectory(autotests) add_subdirectory(tests) endif() ########### next target ############### include(ECMSetupVersion) ecm_setup_version(5.0.0 VARIABLE_PREFIX KDEEDU VERSION_HEADER "${CMAKE_BINARY_DIR}/keduvocdocument/keduvocdocument_version.h" PACKAGE_VERSION_FILE "${CMAKE_BINARY_DIR}/KEduVocDocumentVersion.cmake") include_directories( ${CMAKE_CURRENT_BINARY_DIR} ) set(keduvocdocument_LIB_SRCS keduvocdocument.cpp keduvocidentifier.cpp keduvocexpression.cpp keduvoctranslation.cpp keduvoccontainer.cpp keduvoclesson.cpp keduvocleitnerbox.cpp keduvoctext.cpp keduvocarticle.cpp keduvocconjugation.cpp keduvocpersonalpronoun.cpp keduvocdeclension.cpp keduvocwordtype.cpp keduvockvtmlcompability.cpp keduvockvtml2writer.cpp keduvoccsvwriter.cpp keduvoccontainermodel.cpp keduvoclessonmodel.cpp keduvocreadonlycontainermodel.cpp keduvocvocabularymodel.cpp keduvocwordclassmodel.cpp keduvoccontainermimedata.cpp keduvocvocabularymimedata.cpp keduvocvocabularyfilter.cpp keduvoctranslator.cpp keduvocvocabularydelegate.cpp keduvocvocabularyheaderview.cpp keduvocvocabularycolumnsdialog.cpp keduvoccontainerview.cpp keduvocvocabularyview.cpp keduvocwordtypeview.cpp keduvoclessonview.cpp keduvocaudiowidget.cpp keduvocmultiplechoicewidget.cpp keduvoccomparisonwidget.cpp keduvocdeclensionwidget.cpp keduvocconjugationwidget.cpp keduvocinflectionwidget.cpp keduvocimagewidget.cpp keduvocimagechooserwidget.cpp keduvocsynonymwidget.cpp keduvocsummarywordwidget.cpp keduvoclatexrenderer.cpp keduvoclatexwidget.cpp keduvocscript.cpp keduvocdocumentproperties.cpp keduvoclanguagepropertiespage.cpp keduvoclanguageproperties.cpp + keduvoceditordocument.cpp readerwriters/dummyreader.cpp readerwriters/failedreader.cpp readerwriters/keduvockvtmlreader.cpp readerwriters/keduvockvtml2reader.cpp readerwriters/keduvoccsvreader.cpp readerwriters/keduvocpaukerreader.cpp readerwriters/keduvocvokabelnreader.cpp readerwriters/keduvocwqlreader.cpp readerwriters/keduvocxdxfreader.cpp readerwriters/readermanager.cpp sharedkvtmlfiles.cpp ) ki18n_wrap_ui(keduvocdocument_LIB_SRCS keduvocaudiowidget.ui keduvocmultiplechoicewidget.ui keduvoccomparisonwidget.ui keduvocdeclensionwidget.ui keduvocconjugationwidget.ui keduvocimagechooserwidget.ui keduvocsynonymwidget.ui keduvocsummarywordwidget.ui keduvoclatexwidget.ui keduvocdocumentproperties.ui keduvoclanguagepropertiespage.ui ) include(ECMGenerateHeaders) ecm_generate_headers( KdeEdu_HEADERS HEADER_NAMES KEduVocDocument KEduVocIdentifier KEduVocExpression KEduVocText KEduVocArticle KEduVocConjugation KEduVocLesson KEduVocLeitnerBox KEduVocContainer KEduVocWordFlags KEduVocMultipleChoice KEduVocTranslation KEduVocWordtype KEduVocPersonalPronoun SharedKVTMLFiles KEduVocDeclension KEduVocKVTML2Writer KEduVocContainerModel KEduVocLessonModel KEduVocReadOnlyContainerModel KEduVocVocabularyModel KEduVocWordClassModel KEduVocContainerMimeData KEduVocVocabularyMimeData KEduVocVocabularyFilter KEduVocTranslator KEduVocVocabularyDelegate KEduVocVocabularyHeaderView KEduVocVocabularyColumnsDialog KEduVocContainerView KEduVocVocabularyView KEduVocWordTypeView KEduVocLessonView KEduVocAudioWidget KEduVocMultipleChoiceWidget KEduVocComparisonWidget KEduVocDeclensionWidget KEduVocConjugationWidget KEduVocInflectionWidget KEduVocImageWidget KEduVocImageChooserWidget KEduVocSynonymWidget KEduVocSummaryWordWidget KEduVocLatexRenderer KEduVocLatexWidget KEduVocScript KEduVocDocumentProperties KEduVocLanguagePropertiesPage KEduVocLanguageProperties + KEduVocEditorDocument REQUIRED_HEADERS KdeEdu_HEADERS ) add_library(KEduVocDocument SHARED ${keduvocdocument_LIB_SRCS}) generate_export_header(KEduVocDocument BASE_NAME KEduVocDocument) # vHanda: Add library alias? target_link_libraries(KEduVocDocument PUBLIC Qt5::Xml Qt5::Gui Qt5::Core Qt5::Widgets Qt5::DBus Qt5::Multimedia PRIVATE KF5::I18n KF5::KIOCore KF5::KIOFileWidgets KF5::KIOWidgets KF5::KIONTLM KF5::Archive KF5::Completion KF5::WidgetsAddons KF5::SonnetCore KF5::SonnetUi KF5::Notifications KF5::XmlGui KF5::KrossCore KF5::KrossUi + KF5::NewStuff ) # vHanda: Add Export Name? set_target_properties(KEduVocDocument PROPERTIES VERSION ${KDEEDU_VERSION_STRING} SOVERSION ${KDEEDU_SOVERSION} ) target_include_directories(KEduVocDocument INTERFACE "$") #Library for non-api unittests add_library(keduvocdocument_static STATIC ${keduvocdocument_LIB_SRCS}) set_target_properties(keduvocdocument_static PROPERTIES COMPILE_FLAGS -DKEDUVOCDOCUMENT_STATIC_DEFINE) target_link_libraries(keduvocdocument_static PUBLIC KF5::KIOCore Qt5::Xml Qt5::Core Qt5::Gui Qt5::Widgets Qt5::DBus Qt5::Multimedia PRIVATE KF5::I18n KF5::KIOCore KF5::KIOFileWidgets KF5::KIOWidgets KF5::KIONTLM KF5::Archive KF5::Completion KF5::WidgetsAddons KF5::SonnetCore KF5::SonnetUi KF5::Notifications KF5::XmlGui KF5::KrossCore KF5::KrossUi + KF5::NewStuff ) # if we want to set our own version instead of following kde generic #set(LIB_KEDUVOCDOCUMENT_VERSION "5.0.0") #set(LIB_KEDUVOCDOCUMENT_SOVERSION "5") #set_target_properties(keduvocdocument # PROPERTIES VERSION ${LIB_KEDUVOCDOCUMENT_VERSION} # SOVERSION ${LIB_KEDUVOCDOCUMENT_SOVERSION} #) install(TARGETS KEduVocDocument EXPORT LibKEduVocDocumentTargets ${INSTALL_TARGETS_DEFAULT_ARGS}) ########### install files ############### install(FILES ${CMAKE_CURRENT_BINARY_DIR}/keduvocdocument_export.h ${KdeEdu_HEADERS} DESTINATION ${INCLUDE_INSTALL_DIR}/libkeduvocdocument COMPONENT Devel ) diff --git a/keduvocdocument/keduvoceditordocument.cpp b/keduvocdocument/keduvoceditordocument.cpp new file mode 100644 index 0000000..c215138 --- /dev/null +++ b/keduvocdocument/keduvoceditordocument.cpp @@ -0,0 +1,820 @@ +/*************************************************************************** + + Copyright 2007-2008 Frederik Gladhorn + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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 "keduvoceditordocument.h" + +/*#include "../config-parley.h" +#include "parleymainwindow.h" +#include "editor/editor.h" +#include "version.h" +#include "prefs.h" +#include "languagesettings.h" + +#include "dashboard/dashboard.h"*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_LIBXSLT +//#include "exportdialog.h" +#include +#include +#include +#include +#include +#include +#endif + + +class KEduVocEditorDocument::Private +{ +public: + Private( QWidget* parent ); + + QWidget *m_parent; // Pointer to the owner of this document + QTimer *m_backupTimer; // Timer for next autosave + + // The contents of the document + KEduVocDocument *m_doc; + + bool m_autoBackup; // Prefs::autoBackup() + QString m_separator; // Prefs::separator() + bool m_autoSave; // Prefs::autoSave() + bool m_queryClose; // ParleyMainWindow::queryClose() + int m_backupTime; // Prefs::backupTime() +}; + +KEduVocEditorDocument::Private::Private( QWidget* parent ) +{ + m_parent = parent; + m_backupTimer = 0; + m_doc = 0; +} + +namespace DocumentHelper +{ +void fetchGrammar( KEduVocDocument* doc, int languageIndex ) +{ + QString locale = doc->identifier( languageIndex ).locale(); + + QUrl location( QUrl::fromUserInput( QString( "http://edu.kde.org/parley/locale/" ) + locale + QString( ".kvtml" ) ) ); + + KEduVocDocument grammarDoc; + if( grammarDoc.open( location ) == KEduVocDocument::NoError ) { + doc->identifier( languageIndex ).setArticle( grammarDoc.identifier( 0 ).article() ); + doc->identifier( languageIndex ).setPersonalPronouns( grammarDoc.identifier( 0 ).personalPronouns() ); + // @todo m_doc->identifier(index).setDeclension(grammarDoc.identifier(0).declension()); + doc->identifier( languageIndex ).setTenseList( grammarDoc.identifier( 0 ).tenseList() ); + } else { + qDebug() << "Download of " << location << " failed."; + } +} +} // namespace DocumentHelper + + +KEduVocEditorDocument::KEduVocEditorDocument( QWidget* parent ) + : QObject( parent ) + ,d( new Private( parent ) ) +{ + d->m_doc = new KEduVocDocument( this ); +} + +KEduVocEditorDocument::~KEduVocEditorDocument() +{ + close(); + delete d; + emit documentChanged( 0 ); +} + + +void KEduVocEditorDocument::loadLanguageSettings( QString locale ) { + emit languageSettingsChanged( locale ); +} + +void KEduVocEditorDocument::loadEditorFont( QString locale, KEduVocLanguagePropertiesPage* page ) { + emit editorFontChanged( locale, page ); +} + +void KEduVocEditorDocument::loadPracticeFont( QString locale, KEduVocLanguagePropertiesPage* page ) { + emit practiceFontChanged( locale, page ); +} + +void KEduVocEditorDocument::loadKeyboardLayout( QString locale, KEduVocLanguagePropertiesPage* page ) { + emit keyboardLayoutChanged( locale, page ); +} + +void KEduVocEditorDocument::loadSpellChecker( QString locale, KEduVocLanguagePropertiesPage* page ) { + emit spellCheckerChanged( locale, page ); +} + +void KEduVocEditorDocument::saveEditorFont( QString locale, QFont font ) { + emit storeEditorFont( locale, font ); +} + +void KEduVocEditorDocument::savePracticeFont( QString locale, QFont font ) { + emit storePracticeFont( locale, font ); +} + +void KEduVocEditorDocument::saveKeyboardLayout( QString locale, QString keyboardLayout ) { + emit storeKeyboardLayout( locale, keyboardLayout ); +} + +void KEduVocEditorDocument::saveSpellChecker( QString locale, QString spellChecker ) { + emit storeSpellChecker( locale, spellChecker ); +} + +void KEduVocEditorDocument::storeSettings( QString locale ) { + emit saveSettings( locale ); +} + + +KEduVocDocument *KEduVocEditorDocument::document() +{ + // If there is no present vocabulary document, create an empty one. + if( !d->m_doc ) { + d->m_doc = new KEduVocDocument(); + } + + return d->m_doc; +} + +void KEduVocEditorDocument::setTitle( const QString& title ) +{ + d->m_doc->setTitle( title ); +} + +void KEduVocEditorDocument::slotFileNew() +{ + if( queryClose() ) { + newDocument( true ); + } +} + +bool KEduVocEditorDocument::autoBackup() +{ + return d->m_autoBackup; +} + +void KEduVocEditorDocument::setAutoBackup( bool autoBackup ) +{ + d->m_autoBackup = autoBackup; +} + +QString KEduVocEditorDocument::separator() +{ + return d->m_separator; +} + +void KEduVocEditorDocument::setSeparator( QString separator ) +{ + d->m_separator = separator; +} + +bool KEduVocEditorDocument::autoSave() +{ + return d->m_autoSave; +} + +void KEduVocEditorDocument::setAutoSave( bool autoSave ) +{ + d->m_autoSave = autoSave; +} + +int KEduVocEditorDocument::backupTime() +{ + return d->m_backupTime; +} + +void KEduVocEditorDocument::setBackupTime( int backupTime ) +{ + d->m_backupTime = backupTime; +} + +void KEduVocEditorDocument::setQueryClose( bool queryClose ) +{ + d->m_queryClose = queryClose; +} + +void KEduVocEditorDocument::newDocument( bool wizard ) +{ + KEduVocDocument *newDoc = new KEduVocDocument(); + + initializeDefaultGrammar( newDoc ); + setDefaultDocumentProperties( newDoc ); + bool showGrammarDialog = false; + bool fetchGrammarOnline = false; + if( wizard ) { + KEduVocDocumentProperties* titleAuthorWidget = new KEduVocDocumentProperties( newDoc, true, d->m_parent ); + + QDialogButtonBox * button_dialog = new QDialogButtonBox; + button_dialog->setStandardButtons( QDialogButtonBox::Ok | QDialogButtonBox::Cancel ); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget( titleAuthorWidget ); + layout->addWidget( button_dialog ); + + QDialog * titleAuthorDialog = new QDialog; + titleAuthorDialog->setLayout( layout ); + titleAuthorDialog->setWindowTitle( i18nc( "@title:window document properties", "Properties for %1", newDoc->url().url() ) ); + + connect( titleAuthorDialog, &QDialog::accepted, titleAuthorWidget, &KEduVocDocumentProperties::accept ); + connect( button_dialog, &QDialogButtonBox::accepted, titleAuthorDialog, &QDialog::accept ); + connect( button_dialog, &QDialogButtonBox::rejected, titleAuthorDialog, &QDialog::reject ); + + if( titleAuthorDialog->exec() ) { + showGrammarDialog = titleAuthorWidget->isGrammarCheckBoxChecked(); + fetchGrammarOnline = titleAuthorWidget->isDownloadGrammarCheckBoxChecked(); + delete titleAuthorDialog; + } else { + delete titleAuthorDialog; + delete newDoc; + return; + } + } + + close(); + if( d->m_doc ) { + d->m_doc->deleteLater(); + } + d->m_doc = newDoc; + emit documentChanged( d->m_doc ); + emit autoBackupChanged(); + enableAutoBackup( d->m_autoBackup ); + + if (fetchGrammarOnline) { + DocumentHelper::fetchGrammar( d->m_doc, 0 ); + DocumentHelper::fetchGrammar( d->m_doc, 1 ); + } + if( showGrammarDialog ) { + languageProperties(); + } + + emit showEditor(); +} + +void KEduVocEditorDocument::slotFileOpen() +{ + if( queryClose() ) { + ///@todo frameworks check filters are fixed in kvocdoc + ///@todo frameworks check how to add child checkbox to this dialog + QFileDialog dialog( d->m_parent, i18n( "Open Vocabulary Collection" ), QString(), KEduVocDocument::pattern( KEduVocDocument::Reading ) ); + QCheckBox *practiceCheckBox = new QCheckBox( i18n( "Open in practice &mode" ), &dialog ); + emit checkBoxChanged( practiceCheckBox ); + dialog.setFileMode( QFileDialog::ExistingFile ); + if( dialog.exec() + && !dialog.selectedFiles().isEmpty() + && open( QUrl::fromLocalFile( dialog.selectedFiles().first() ) ) + ) { + if( practiceCheckBox->isChecked() ) { + emit showPracticeConfiguration(); + } else { + emit showEditor(); + } + } + } +} + +void KEduVocEditorDocument::slotFileOpenRecent( const QUrl& url ) +{ + if( queryClose() && open( url ) ) { + ///@todo: start practice directly depending on current component + emit showEditor(); + } +} + +bool KEduVocEditorDocument::open( const QUrl & url ) +{ + if( url.path().isEmpty() ) { + return false; + } + + close(); + + if( d->m_doc ) { + d->m_doc->deleteLater(); + } + d->m_doc = new KEduVocDocument( this ); + emit documentChanged( d->m_doc ); + emit separatorChanged(); + d->m_doc->setCsvDelimiter( d->m_separator ); + + bool isSuccess = false, isError = false; + + KEduVocDocument::ErrorCode ret = d->m_doc->open( url, KEduVocDocument::FileDefaultHandling ); + switch( ret ) { + case KEduVocDocument::NoError : + isSuccess = true; + break; + case KEduVocDocument::FileLocked : + { + int exit = KMessageBox::warningYesNo( + d->m_parent, i18n( "The vocabulary collection is locked by another process. You can open the file if you take over the lock, but you will lose any changes from the other process.\n\nDo you want to take over the lock?\n" ), i18n( "Take Over Lock" ) ) ; + if ( exit == KMessageBox::Yes ) { //attempt to steal lock + + ret = d->m_doc->open( url, KEduVocDocument::FileIgnoreLock ); + if ( ret == KEduVocDocument::NoError ) { + qDebug() << "Lock stolen"; + isSuccess = true; + } else { + isError = true; + } + } else { //Don't Steal continue work without saving !!! + } + + break; + } + default: + isError = true; + } + + if( isSuccess ) { + qDebug() << "Open success."; + //m_parleyApp->editor()->updateDocument(); + emit recentFileChanged( url, d->m_doc->title() ); + + emit autoBackupChanged(); + enableAutoBackup( d->m_autoBackup ); + + } else { + if( isError ) { + KMessageBox::error( + d->m_parent, i18n( "Opening collection \"%1\" resulted in an error: %2", d->m_doc->url().url(), + d->m_doc->errorDescription( ret ) ), i18nc( "@title:window", "Open Collection" ) ); + } + d->m_doc->deleteLater(); + emit documentChanged( 0 ); + d->m_doc = 0; + } + + return isSuccess; +} + +void KEduVocEditorDocument::close() +{ + enableAutoBackup( false ); + if( d->m_doc ) { + emit documentChanged( 0 ); + d->m_doc->deleteLater(); + d->m_doc = 0; + } +} + +bool KEduVocEditorDocument::queryClose() +{ + if( ( d->m_doc == NULL ) || !d->m_doc->isModified() ) { + return true; + } + + emit prefsSelfSave(); + + emit autoSaveChanged(); //save without asking + bool canSave = d->m_autoSave; + + if( !canSave ) { + int exit = KMessageBox::warningYesNoCancel( + d->m_parent, i18n( "Vocabulary is modified.\n\nSave file before exit?\n" ), + "", KStandardGuiItem::save(), KStandardGuiItem::discard() ); + switch( exit ) { + case KMessageBox::Yes : + canSave = true; // save and exit + break; + case KMessageBox::No : + canSave = false; // don't save but exit + break; + case KMessageBox::Continue : + default: + return false; // continue work without saving !!! + } + } + + if( canSave ) { + save(); // save and exit + } + + close(); + return true; +} + + +void KEduVocEditorDocument::openGHNS() +{ + emit queryCloseChanged(); + if( d->m_queryClose ) { + QDir downloadDir( QStandardPaths::writableLocation( QStandardPaths::DataLocation ) + '/' + "kvtml/" ); + + downloadDir.mkpath( downloadDir.absolutePath() ); + + QUrl url = QUrl::fromUserInput( QFileDialog::getOpenFileName( + d->m_parent + , i18n( "Open Downloaded Vocabulary Collection" ) + , downloadDir.path() + , KEduVocDocument::pattern( KEduVocDocument::Reading ) ) ); + + if( open( url ) ) { + emit showPracticeConfiguration(); + } + } +} + +void KEduVocEditorDocument::save() +{ + if( d->m_doc->url().fileName() == i18n( "Untitled" ) ) { + saveAs(); + return; + } + + // remove previous backup + QFile::remove( d->m_doc->url().toLocalFile() + '~' ); + QFile::copy( QFile::encodeName( d->m_doc->url().toLocalFile() ), QFile::encodeName( d->m_doc->url().toLocalFile() + '~' ) ); + + emit separatorChanged(); + d->m_doc->setCsvDelimiter( d->m_separator ); + + emit statesNeedSaving(); + + QString newgenerator = QApplication::applicationName() + QApplication::applicationVersion(); + d->m_doc->setGenerator( newgenerator ); + + bool isSuccess = false, isError = false ; + + KEduVocDocument::ErrorCode ret = d->m_doc->saveAs( + d->m_doc->url() , KEduVocDocument::Automatic, KEduVocDocument::FileIgnoreLock ); + + switch( ret ) { + case KEduVocDocument::NoError : + isSuccess = true; + break; + case KEduVocDocument::FileLocked : + { + int exit = KMessageBox::warningYesNo( + d->m_parent, i18n( "File \"%1\" is locked by another process. You can save to the file if you take over the lock, but you will lose any changes from the other process.\n\nDo you want to take over the lock?\n" + , d->m_doc->url().url() ), "" ); + if( exit == KMessageBox::Yes ) { + d->m_doc->setGenerator( newgenerator ); + ret = d->m_doc->saveAs( d->m_doc->url() , KEduVocDocument::Automatic, KEduVocDocument::FileIgnoreLock ); + + if( ret == KEduVocDocument::NoError ) { + isSuccess = true; + qDebug() << "Lock stolen"; + } else { + isError = true; + } + } else { + //Intentionally empty else. Try to saveAs another filename + } + break; + } + default: + isError = true; + } + + if( isSuccess ) { + emit recentFileChanged( d->m_doc->url(), d->m_doc->title() ); + emit autoBackupChanged(); + enableAutoBackup( d->m_autoBackup ); + } else { + if( isError ) { + KMessageBox::error( + d->m_parent, i18n( "Writing file \"%1\" resulted in an error: %2", d->m_doc->url().url(), + d->m_doc->errorDescription( ret ) ), i18nc( "@title:window", "Save File" ) ); + } + qDebug() << "Save failed trying save as for "<< d->m_doc->url().url(); + saveAs(); + } + +} + +void KEduVocEditorDocument::saveAs( QUrl url ) +{ + if( !d->m_doc ) { + return; + } + + if( url.isEmpty() ) { + url = QUrl::fromLocalFile( QFileDialog::getSaveFileName( + d->m_parent->parentWidget() + , i18n( "Save Vocabulary As" ) + , QString() + , KEduVocDocument::pattern( KEduVocDocument::Writing ) ) + ); + + if( url.isEmpty() ) { + return; + } + } + + QFileInfo fileinfo( url.toLocalFile() ); + if( fileinfo.exists() ) { + if( KMessageBox::warningContinueCancel( + 0, i18n( "The file

%1

already exists. Do you want to overwrite it?
", + url.toLocalFile() ), QString(), KStandardGuiItem::overwrite() ) == KMessageBox::Cancel ) { + return; + } + } + + QString msg = i18nc( "@info:status saving a file", "Saving %1", url.toLocalFile() ); + + QFile::remove( url.toLocalFile() + '~' ); // remove previous backup + QFile::copy( QFile::encodeName( url.toLocalFile() ), QFile::encodeName( QString( url.toLocalFile() + '~' ) ) ); + + emit separatorChanged(); + d->m_doc->setCsvDelimiter( d->m_separator ); + + if( !url.toLocalFile().contains( '.' ) ) { + url.fromLocalFile( url.toLocalFile() + QString::fromLatin1( ".kvtml" ) ); + } + + bool isSuccess = false, isError = false; + d->m_doc->setGenerator( "Parley" ); + int ret = d->m_doc->saveAs( url, KEduVocDocument::Automatic ); + switch( ret ) { + case KEduVocDocument::NoError : + isSuccess = true; + break; + case KEduVocDocument::FileLocked : + { + int exit = KMessageBox::warningYesNo( + d->m_parent, i18n( "File \"%1\" is locked by another process. You can save to the file if you take over the lock, but you will lose any changes from the other process.\n\nDo you want to take over the lock?\n" + , d->m_doc->url().url() ), "" ); + if( exit == KMessageBox::Yes ) { //attempt lock steal + d->m_doc->setGenerator( QApplication::applicationName() + QApplication::applicationVersion() ); + ret = d->m_doc->saveAs( + d->m_doc->url() , KEduVocDocument::Automatic, KEduVocDocument::FileIgnoreLock ); + + if( ret == KEduVocDocument::NoError ) { + isSuccess = true; + qDebug() << "Lock stolen"; + } else { + isError = true; + } + break; + } else { //don't steal the lock + } + + break; + } + default: + isError = true; + break; + } + + if( isSuccess ) { + qDebug() << "SaveAs success."; + emit recentFileChanged( d->m_doc->url(), d->m_doc->title() ); + emit statesNeedSaving(); + + } else { + qDebug() << "SaveAs failed for "<< d->m_doc->url().url() << " \nwhy "<< d->m_doc->errorDescription( ret ); + if( isError ) { + KMessageBox::error( + d->m_parent, i18n( "Writing file \"%1\" resulted in an error: %2", + d->m_doc->url().url(), d->m_doc->errorDescription( ret ) ), i18nc( "@title:window", "Save File" ) ); + + } + } + +} + +void KEduVocEditorDocument::initializeDefaultGrammar( KEduVocDocument *doc ) +{ + KEduVocWordType *root = doc->wordTypeContainer(); + KEduVocWordType *noun = new KEduVocWordType( i18n( "Noun" ), root ); + noun->setWordType( KEduVocWordFlag::Noun ); + root->appendChildContainer( noun ); + + KEduVocWordType *nounChild = new KEduVocWordType( i18n( "Masculine" ), noun ); + nounChild->setWordType( KEduVocWordFlag::Noun | KEduVocWordFlag::Masculine ); + noun->appendChildContainer( nounChild ); + nounChild = new KEduVocWordType( i18n( "Feminine" ), noun ); + nounChild->setWordType( KEduVocWordFlag::Noun | KEduVocWordFlag::Feminine ); + noun->appendChildContainer( nounChild ); + nounChild = new KEduVocWordType( i18n( "Neuter" ), noun ); + nounChild->setWordType( KEduVocWordFlag::Noun | KEduVocWordFlag::Neuter ); + noun->appendChildContainer( nounChild ); + + KEduVocWordType *verb = new KEduVocWordType( i18n( "Verb" ), root ); + verb->setWordType( KEduVocWordFlag::Verb ); + root->appendChildContainer( verb ); + + KEduVocWordType *adjective = new KEduVocWordType( i18n( "Adjective" ), root ); + adjective->setWordType( KEduVocWordFlag::Adjective ); + root->appendChildContainer( adjective ); + + KEduVocWordType *adverb = new KEduVocWordType( i18n( "Adverb" ), root ); + adverb->setWordType( KEduVocWordFlag::Adverb ); + root->appendChildContainer( adverb ); + + KEduVocWordType *conjunction = new KEduVocWordType( i18n( "Conjunction" ), root ); + conjunction->setWordType( KEduVocWordFlag::Conjunction ); + root->appendChildContainer( conjunction ); +} + + +void KEduVocEditorDocument::setDefaultDocumentProperties( KEduVocDocument *doc ) +{ + KEMailSettings emailSettings; + emailSettings.setProfile( emailSettings.defaultProfileName() ); + doc->setAuthor( emailSettings.getSetting( KEMailSettings::RealName ) ); + doc->setAuthorContact( emailSettings.getSetting( KEMailSettings::EmailAddress ) ); + + doc->setLicense( i18n( "Public Domain" ) ); + doc->setCategory( i18n( "Languages" ) ); + + QString locale = QLocale().name(); + + doc->appendIdentifier(); + doc->appendIdentifier(); + doc->identifier( 0 ).setName(QLocale( locale ).nativeLanguageName() ); + doc->identifier( 0 ).setLocale( locale ); + doc->identifier( 1 ).setName( i18n( "A Second Language" ) ); + doc->identifier( 1 ).setLocale( locale ); + + KEduVocLesson* lesson = new KEduVocLesson( i18n( "Lesson 1" ), doc->lesson() ); + doc->lesson()->appendChildContainer( lesson ); + + // add some entries + for( int i = 0; i < 15 ; i++ ) { + lesson->appendEntry( new KEduVocExpression() ); + } + + doc->setModified( false ); +} + +void KEduVocEditorDocument::slotGHNS() +{ + QMimeDatabase db; + QString fileName; + KNS3::DownloadDialog newStuffDialog( d->m_parent ); + newStuffDialog.exec(); + KNS3::Entry::List entries = newStuffDialog.installedEntries(); + int numberInstalled = entries.size(); + foreach( const KNS3::Entry & entry, entries ) { + // check mime type and if kvtml, open it + foreach( const QString & file, entry.installedFiles() ) { + QMimeType mimeType = db.mimeTypeForFile( file ); + qDebug() << "KNS3 file of mime type:" << db.mimeTypeForFile( file ).name(); + if( mimeType.inherits( "application/x-kvtml" ) ) { + emit recentFileChanged( QUrl::fromLocalFile( file ), QString() ); + fileName = file; + } + } + } + + // to enable the display in the welcome screen + emit prefsSelfSave(); + emit updateRecentFilesModel(); + if( numberInstalled > 1 ) { + openGHNS(); + } else if( numberInstalled == 1 ) { + if( open( QUrl::fromUserInput( fileName ) ) ) + emit showPracticeConfiguration(); + else + KMessageBox::error( d->m_parent, i18n( "Could not open vocabulary collection \"%1\"", entries.first().name() ) ); + } +} + +void KEduVocEditorDocument::documentProperties() +{ + KEduVocDocumentProperties* titleAuthorWidget = new KEduVocDocumentProperties( d->m_doc, false, d->m_parent ); + + QDialogButtonBox * button_dialog = new QDialogButtonBox; + button_dialog->setStandardButtons( QDialogButtonBox::Ok | QDialogButtonBox::Cancel ); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget( titleAuthorWidget ); + layout->addWidget( button_dialog ); + + QDialog * titleAuthorDialog = new QDialog; + titleAuthorDialog->setLayout( layout ); + titleAuthorDialog->setWindowTitle( i18nc( "@title:window document properties", "Properties for %1", d->m_doc->url().url() ) ); + + // the language options are only shown, when this is used to create a new document. + titleAuthorWidget->setLanguageGroupBoxVisible( false ); + + connect( titleAuthorDialog, &QDialog::accepted, titleAuthorWidget, &KEduVocDocumentProperties::accept ); + connect( button_dialog, &QDialogButtonBox::accepted, titleAuthorDialog, &QDialog::accept ); + connect( button_dialog, &QDialogButtonBox::rejected, titleAuthorDialog, &QDialog::reject ); + + titleAuthorDialog->exec(); + delete titleAuthorDialog; + emit documentChanged( d->m_doc ); +} + +void KEduVocEditorDocument::languageProperties() +{ + KEduVocLanguageProperties *properties = new KEduVocLanguageProperties( d->m_doc, d->m_parent ); + connect( properties, &KEduVocLanguageProperties::languageSettingsChanged, this, &KEduVocEditorDocument::loadLanguageSettings ); + connect( properties, &KEduVocLanguageProperties::editorFontChanged, this, &KEduVocEditorDocument::loadEditorFont ); + connect( properties, &KEduVocLanguageProperties::practiceFontChanged, this, &KEduVocEditorDocument::loadPracticeFont ); + connect( properties, &KEduVocLanguageProperties::keyboardLayoutChanged, this, &KEduVocEditorDocument::loadKeyboardLayout ); + connect( properties, &KEduVocLanguageProperties::spellCheckerChanged, this, &KEduVocEditorDocument::loadSpellChecker ); + connect( properties, &KEduVocLanguageProperties::storeEditorFont, this, &KEduVocEditorDocument::saveEditorFont ); + connect( properties, &KEduVocLanguageProperties::storePracticeFont, this, &KEduVocEditorDocument::savePracticeFont ); + connect( properties, &KEduVocLanguageProperties::storeKeyboardLayout, this, &KEduVocEditorDocument::saveKeyboardLayout ); + connect( properties, &KEduVocLanguageProperties::storeSpellChecker, this, &KEduVocEditorDocument::saveSpellChecker );; + connect( properties, &KEduVocLanguageProperties::saveSettings, this, &KEduVocEditorDocument::storeSettings ); + + if( properties->exec() == QDialog::Accepted ) { + emit languagesChanged(); + } +} + +void KEduVocEditorDocument::uploadFile() +{ + // save file to temp location + QTemporaryDir dir; + if( ! dir.isValid() ) { + KMessageBox::error( d->m_parent, i18n( "Could not create temporary directory \"%1\"", dir.path() ) ); + return; + } + QUrl url( QUrl::fromUserInput( dir.path() + d->m_doc->url().fileName() ) ); + qDebug() << "save in " << url; + d->m_doc->setGenerator( "Parley" ); + if( d->m_doc->saveAs( url, KEduVocDocument::Automatic ) != KEduVocDocument::NoError ) { + KMessageBox::error( d->m_parent, i18n( "Could not save vocabulary collection \"%1\"", url.toString() ) ); + return; + } + + KEduVocDocument tempDoc( this ); + if( tempDoc.open( url ) != KEduVocDocument::NoError ) { + KMessageBox::error( d->m_parent, i18n( "Could not open vocabulary collection \"%1\"", url.toString() ) ); + return; + } + + // remove grades + tempDoc.lesson()->resetGrades( -1, KEduVocContainer::Recursive ); + d->m_doc->setGenerator( "Parley" ); + if( tempDoc.saveAs( url, KEduVocDocument::Automatic ) != KEduVocDocument::NoError ) { + KMessageBox::error( d->m_parent, i18n( "Could not save vocabulary collection \"%1\"", url.toString() ) ); + return; + } + + // upload + KNS3::UploadDialog dialog( d->m_parent ); + dialog.setUploadFile(url); + dialog.exec(); +} + + +void KEduVocEditorDocument::exportDialog() +{ + /** +#ifdef HAVE_LIBXSLT + KEduVocExportDialog dialog( d->m_doc, m_parent ); + dialog.exec(); +#endif +*/ +} + + +void KEduVocEditorDocument::enableAutoBackup( bool enable ) +{ + if( !enable ) { + if( d->m_backupTimer ) { + d->m_backupTimer->stop(); + } + } else { + if( !d->m_backupTimer ) { + d->m_backupTimer = new QTimer( this ); + connect( d->m_backupTimer, &QTimer::timeout, this, &KEduVocEditorDocument::save ); + } + emit backupTimeChanged(); + d->m_backupTimer->start( d->m_backupTime * 60 * 1000 ); + } +} diff --git a/keduvocdocument/keduvoceditordocument.h b/keduvocdocument/keduvoceditordocument.h new file mode 100644 index 0000000..d8cc673 --- /dev/null +++ b/keduvocdocument/keduvoceditordocument.h @@ -0,0 +1,335 @@ +/*************************************************************************** + + Copyright 2007 Frederik Gladhorn + + ***************************************************************************/ + +/*************************************************************************** + * * + * 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. * + * * + ***************************************************************************/ +#ifndef KEDUVOCEDITORDOCUMENT_H +#define KEDUVOCEDITORDOCUMENT_H + +#include +#include + +#include + +class QTimer; +class QCheckBox; +class KEduVocLanguagePropertiesPage; + +/** + @author Frederik Gladhorn +*/ +class KEDUVOCDOCUMENT_EXPORT KEduVocEditorDocument : public QObject +{ + Q_OBJECT +public: + KEduVocEditorDocument( QWidget* parent ); + ~KEduVocEditorDocument(); + + + KEduVocDocument *document(); + + void setTitle( const QString& title ); + + /** Enable/disable the timed auto backup + @todo Move autobackup functionality into libkdeedu which is responsible for + file opening/closing and locking already.*/ + void enableAutoBackup( bool enable ); + //void fetchGrammar(int languageIndex); + +public slots: + /** open a new application window */ + void slotFileNew(); + + /** open a document */ + void slotFileOpen(); + + /** opens a file from the recent files menu */ + void slotFileOpenRecent( const QUrl& url ); + /** open a downloaded (knewstuff/get hot new stuff) document */ + void openGHNS(); + /** download new vocabularies */ + void slotGHNS(); + /** upload the current file */ + void uploadFile(); + + /** Opens the given url, displays an error message and returns false on failure */ + bool open(const QUrl &); + + /** close the document*/ + void close(); + /** When quitting, ask for confirmation if the doc has not been saved */ + bool queryClose(); + + + /** save a document */ + void save(); + void saveAs( QUrl file = QUrl() ); + + void exportDialog(); + + void newDocument(bool wizard); + + /** General doc properties like title, author etc */ + void documentProperties(); + void languageProperties(); + + /** Slots for KEduVocLanguageProperties signals */ + void loadLanguageSettings( QString locale ); + void loadEditorFont( QString locale, KEduVocLanguagePropertiesPage* page ); + void loadPracticeFont( QString locale, KEduVocLanguagePropertiesPage* page ); + void loadKeyboardLayout( QString locale, KEduVocLanguagePropertiesPage* page ); + void loadSpellChecker( QString locale, KEduVocLanguagePropertiesPage* page ); + void saveEditorFont( QString locale, QFont font ); + void savePracticeFont( QString locale, QFont font ); + void saveKeyboardLayout( QString locale, QString keyboardLayout ); + void saveSpellChecker( QString locale, QString spellChecker ); + void storeSettings( QString locale ); + + bool autoBackup(); + void setAutoBackup( bool autoBackup ); + + QString separator(); + void setSeparator( QString separator ); + + bool autoSave(); + void setAutoSave( bool autoSave ); + + void setQueryClose( bool queryClose ); + + int backupTime(); + void setBackupTime( int backupTime ); + +signals: + /** Emitted when the document pointer is changed. + @todo Stop using documentChanged(0) as a replacement for destoyed in editor classes.**/ + void documentChanged( KEduVocDocument *newDocument ); + void languagesChanged(); + void statesNeedSaving(); + + /** + * Sample corresponding slot for calling class : + * + * void loadLanguageSettings( QString locale ) { + * LanguageSettings settings( locale ); + * settings.load(); + * } + */ + void languageSettingsChanged( QString ); + + /** + * Sample corresponding slot for calling class : + * + * void loadEditorFont( QString locale, KEduVocLanguagePropertiesPage* page ) { + * LanguageSettings settings( locale ); + * settings.load(); + * page->setEditorFont( settings.editorFont() ); + * } + */ + void editorFontChanged( QString, KEduVocLanguagePropertiesPage* ); + + /** + * Sample corresponding slot for calling class : + * + * void loadPracticeFont( QString locale, KEduVocLanguagePropertiesPage* page ) { + * LanguageSettings settings( locale ); + * settings.load(); + * page->setPracticeFont( settings.practiceFont() ); + * } + */ + void practiceFontChanged( QString, KEduVocLanguagePropertiesPage* ); + + /** + * Sample corresponding slot for calling class : + * + * void loadKeyboardLayout( QString locale, KEduVocLanguagePropertiesPage* page ) { + * LanguageSettings settings( locale ); + * settings.load(); + * page->setKeyboardLayout( settings.keyboardLayout() ); + * } + */ + void keyboardLayoutChanged( QString, KEduVocLanguagePropertiesPage* ); + + /** + * Sample corresponding slot for calling class : + * + * void loadSpellChecker( QString locale, KEduVocLanguagePropertiesPage* page ) { + * LanguageSettings settings( locale ); + * settings.load(); + * page->setSpellChecker( settings.spellChecker() ); + * } + */ + void spellCheckerChanged( QString, KEduVocLanguagePropertiesPage* ); + + /** + * Sample corresponding slot for calling class : + * + * void saveEditorFont( QString locale, QFont font ) { + * LanguageSettings settings( locale ); + * settings.load(); + * settings.setEditorFont( font ); + * } + */ + void storeEditorFont( QString, QFont ); + + /** + * Sample corresponding slot for calling class : + * + * void savePracticeFont( QString locale, QFont font ) { + * LanguageSettings settings( locale ); + * settings.load(); + * settings.setPracticeFont( font ); + * } + */ + void storePracticeFont( QString, QFont ); + + /** + * Sample corresponding slot for calling class : + * + * void saveKeyboardLayout( QString locale, QString keyboardLayout ) { + * LanguageSettings settings( locale ); + * settings.load(); + * settings.setKeyboardLayout( keyboardLayout ); + * } + */ + void storeKeyboardLayout( QString, QString ); + + /** + * Sample corresponding slot for calling class : + * + * void saveSpellChecker( QString locale, QString spellChecker ) { + * LanguageSettings settings( locale ); + * settings.load(); + * settings.setSpellChecker( spellChecker ); + * } + */ + void storeSpellChecker( QString, QString ); + + /** + * Sample corresponding slot for calling class : + * + * void storeSettings( QString locale ) { + * LanguageSettings settings( locale ); + * settings.load(); + * settings.save(); + * } + */ + void saveSettings( QString ); + + + /** + * Sample corresponding slot for calling class + * + * void loadAutoBackup() + * { + * editorDoc->setAutoBackup( Prefs::autoBackup() ); + * } + * + * Where editorDoc is a KEduVocEditorDocument object + */ + void autoBackupChanged(); + + /** + * Call ParleyMainWindow::showEditor in corresponding slot + */ + void showEditor(); + + /** Sample corresponding slot for calling class (in ParleyMainWindow) + * + * void setCheckBox( QCheckBox* box ) + * { + * box->setChecked( currentComponent() != ParleyMainWindow::EditorComponent ); + * } + */ + void checkBoxChanged( QCheckBox* box ); + + /** + * Call ParleyMainWindow::showPracticeConfiguration in corresponding slot + */ + void showPracticeConfiguration(); + + /** + * Sample corresponding slot for calling class + * + * void loadSeparator() + * { + * editorDoc->setSeparator( Prefs::separator() ); + * } + * + * Where editorDoc is a KEduVocEditorDocument object + */ + void separatorChanged(); + + /** + * Sample corresponding slot for calling class (in ParleyMainWindow) + * + * void loadRecentFile( const QUrl& url, QString title ) + * { + * addRecentFile( url, title ); + * } + */ + void recentFileChanged( const QUrl& url, QString title ); + + /** + * Call Prefs::self()->save() in corresponding slot + */ + void prefsSelfSave(); + + /** + * Sample corresponding slot for calling class + * + * void loadAutoSave() + * { + * editorDoc->setAutoSave( Prefs::autoSave() ); + * } + * + * Where editorDoc is a KEduVocEditorDocument object + */ + void autoSaveChanged(); + + /** + * Sample corresponding slot for calling class (in ParleyMainWindow) + * + * void loadQueryClose() + * { + * editorDoc->setQueryClose( queryClose() ); + * } + * + * Where editorDoc is a KEduVocEditorDocument object + */ + void queryCloseChanged(); + + /** + * Call ParleyMainWindow::updateRecentFilesModel() in corresponding slot + */ + void updateRecentFilesModel(); + + /** + * Sample corresponding slot for calling class (in ParleyMainWindow) + * + * void loadBackupTime() + * { + * editorDoc->setBackupTime( Prefs::backupTime()) ); + * } + * + * Where editorDoc is a KEduVocEditorDocument object + */ + void backupTimeChanged(); + +private: + void initializeDefaultGrammar( KEduVocDocument *doc ); + void setDefaultDocumentProperties( KEduVocDocument *doc ); + + class Private; + Private * const d; +}; + +#endif