diff --git a/CMakeLists.txt b/CMakeLists.txt index c08c4c9..764917d 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) +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) #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 ba420e7..bc7f82c 100644 --- a/keduvocdocument/CMakeLists.txt +++ b/keduvocdocument/CMakeLists.txt @@ -1,178 +1,193 @@ 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 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 +) + 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 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 ) # 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 ) # 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/keduvocaudiowidget.cpp b/keduvocdocument/keduvocaudiowidget.cpp new file mode 100644 index 0000000..c1fdd8d --- /dev/null +++ b/keduvocdocument/keduvocaudiowidget.cpp @@ -0,0 +1,134 @@ +/*************************************************************************** + + 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. * + * * + ***************************************************************************/ + +#include "keduvocaudiowidget.h" + +#include "ui_keduvocaudiowidget.h" + +#include + +#include +#include + +using namespace Editor; + +class KEduVocAudioWidget::Private +{ +public: + Private(); + + /// Column in the document - corresponds to the language (-KV_COL_TRANS) + int m_currentTranslation; + /// Selection in the doc - if more than one row is selected behavior is different + KEduVocExpression* m_entry; + + QMediaPlayer* m_player; ///< media object for the files + + Ui::KEduVocAudioWidget * m_ui; +}; + +KEduVocAudioWidget::Private::Private() +{ + m_currentTranslation = -1; + m_player = 0; + m_entry = 0; +} + +KEduVocAudioWidget::KEduVocAudioWidget( QWidget *parent ) + : QWidget( parent ) + , d( new Private ) +{ + d->m_ui->setupUi(this); + + connect( d->m_ui->audioUrlRequester, &KUrlRequester::textChanged, this, &KEduVocAudioWidget::slotAudioFileChanged ); + connect( d->m_ui->playButton, &QPushButton::clicked, this, &KEduVocAudioWidget::playAudio ); +// connect(recordButton, SIGNAL(clicked()), SLOT(recordAudio())); + + d->m_ui->playButton->setEnabled( false ); + d->m_ui->playButton->setIcon( QIcon::fromTheme( "media-playback-start" ) ); + d->m_ui->recordButton->setVisible( false ); +// recordButton->setEnabled(false); +// recordButton->setIcon(QIcon::fromTheme("media-record")); + d->m_ui->audioUrlRequester->setEnabled( false ); +} + +KEduVocAudioWidget::~KEduVocAudioWidget() +{ + delete d; +} + +void KEduVocAudioWidget::setTranslation( KEduVocExpression* entry, int translation ) +{ + d->m_currentTranslation = translation; + d->m_entry = entry; + + if( d->m_entry ) { + d->m_ui->recordButton->setEnabled( true ); + d->m_ui->audioUrlRequester->setEnabled( true ); + d->m_ui->audioUrlRequester->setUrl( QUrl::fromLocalFile( d->m_entry->translation( d->m_currentTranslation )->soundUrl().toLocalFile() ) ); + } else { + d->m_ui->recordButton->setEnabled( false ); + d->m_ui->audioUrlRequester->setEnabled( false ); + if( d->m_player ) { + if( d->m_player->state() == QMediaPlayer::PlayingState ) { + d->m_ui->playButton->setEnabled( true ); + } else { + d->m_ui->playButton->setEnabled( false ); + } + } + d->m_ui->audioUrlRequester->clear(); + } +} + +void KEduVocAudioWidget::slotAudioFileChanged( const QString & url ) +{ + if( d->m_entry ) { + d->m_entry->translation( d->m_currentTranslation )->setSoundUrl( QUrl::fromLocalFile( url ) ); + } + d->m_ui->playButton->setEnabled( !url.isEmpty() ); +} + +void KEduVocAudioWidget::playAudio() +{ + QUrl soundFile = d->m_entry->translation( d->m_currentTranslation )->soundUrl(); + + if( !d->m_player ) { + d->m_player = new QMediaPlayer( this ); + connect( d->m_player, SIGNAL( finished() ), SLOT( slotPlaybackFinished() ) ); + } else { + if( d->m_player->state() == QMediaPlayer::PlayingState ) { + d->m_player->stop(); + slotPlaybackFinished(); + } + } + d->m_player->setMedia( soundFile ); + d->m_player->setVolume(50); + + d->m_ui->playButton->setIcon( QIcon::fromTheme( "media-playback-stop" ) ); + d->m_player->play(); +} + +/* +void AudioWidget::recordAudio() +{ + /// FIXME: When Phonon gains the ability to record sound, implement me :) +} +*/ + +void KEduVocAudioWidget::slotPlaybackFinished() +{ + d->m_ui->playButton->setIcon( QIcon::fromTheme( "media-playback-start" ) ); + d->m_ui->playButton->setEnabled( !d->m_ui->audioUrlRequester->url().isEmpty() ); +} diff --git a/keduvocdocument/keduvocaudiowidget.h b/keduvocdocument/keduvocaudiowidget.h new file mode 100644 index 0000000..5fcd146 --- /dev/null +++ b/keduvocdocument/keduvocaudiowidget.h @@ -0,0 +1,59 @@ +/*************************************************************************** + + 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 KEDUVOCAUDIOWIDGET_H +#define KEDUVOCAUDIOWIDGET_H + +#include + +//#include "ui_keduvocaudiowidget.h" +#include + +class QMediaPlayer; + +class KEduVocExpression; + +namespace Editor +{ + +class KEDUVOCDOCUMENT_EXPORT KEduVocAudioWidget : public QWidget +{ + Q_OBJECT +public: + explicit KEduVocAudioWidget( QWidget* parent = 0 ); + ~KEduVocAudioWidget(); + +public slots: + /** + * Update the word + * @param entry + * @param translation + */ + void setTranslation( KEduVocExpression* entry, int translation ); + +private slots: + void slotAudioFileChanged( const QString & url ); + void playAudio(); +// void recordAudio(); + void slotPlaybackFinished(); + +private: + class Private; + Private * const d; +}; + +} + +#endif diff --git a/keduvocdocument/keduvocaudiowidget.ui b/keduvocdocument/keduvocaudiowidget.ui new file mode 100644 index 0000000..8c8bde9 --- /dev/null +++ b/keduvocdocument/keduvocaudiowidget.ui @@ -0,0 +1,71 @@ + + KEduVocAudioWidget + + + + 0 + 0 + 236 + 137 + + + + + + + + + Play + + + + + + + Record + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + KUrlRequester + QFrame +
kurlrequester.h
+
+
+ + +
diff --git a/keduvocdocument/keduvocvocabularyview.cpp b/keduvocdocument/keduvocvocabularyview.cpp index 67b43ac..1375baf 100644 --- a/keduvocdocument/keduvocvocabularyview.cpp +++ b/keduvocdocument/keduvocvocabularyview.cpp @@ -1,529 +1,534 @@ /*************************************************************************** Copyright 2006, 2007 Peter Hedlund 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. * * * ***************************************************************************/ ///@file keduvocvocabularyview.cpp #include "keduvocvocabularyview.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 using namespace Editor; class KEduVocVocabularyView::Private { public: Private( KActionCollection* actionCollection, bool automaticTranslation ); KActionCollection* m_actionCollection; QAction* m_appendEntryAction; QAction* m_deleteEntriesAction; QAction* m_copyAction; QAction* m_cutAction; QAction* m_pasteAction; QAction* m_selectAllAction; QAction* m_clearSelectionAction; KEduVocVocabularyFilter* m_model; KEduVocVocabularyDelegate* m_vocabularyDelegate; KEduVocDocument *m_doc; int m_spellColumn; int m_spellRow; Sonnet::BackgroundChecker *m_spellChecker; Sonnet::Dialog *m_spellDialog; bool m_automaticTranslation; // Prefs::automaticTranslation() QList m_visibleColumns; QByteArray m_state; QString m_spellCheck; // LanguageSettings::spellChecker() }; KEduVocVocabularyView::Private::Private( KActionCollection* actionCollection, bool automaticTranslation ) : m_model( 0 ), m_doc( 0 ), m_spellChecker( 0 ), m_spellDialog( 0 ), m_actionCollection( actionCollection ) { m_automaticTranslation = automaticTranslation; } /** FIXME Replace QWidget in constructor with EditorWindow and d->m_actionCollection with parent->actionColletion() after adding editor.h to keduvoc */ KEduVocVocabularyView::KEduVocVocabularyView( QWidget * parent, KActionCollection* actionCollection, bool automaticTranslation ) : QTableView(parent), d( new Private( actionCollection, automaticTranslation ) ) { installEventFilter( this ); setHorizontalHeader( new KEduVocVocabularyHeaderView( Qt::Horizontal, this ) ); horizontalHeader()->setSectionResizeMode( QHeaderView::Interactive ); horizontalHeader()->setSectionsMovable( true ); setEditTriggers( QAbstractItemView::AnyKeyPressed | QAbstractItemView::EditKeyPressed | QAbstractItemView::DoubleClicked ); setSortingEnabled( true ); setTabKeyNavigation( true ); d->m_vocabularyDelegate = new KEduVocVocabularyDelegate( d->m_automaticTranslation, this ); setItemDelegate( d->m_vocabularyDelegate ); setFrameStyle( QFrame::NoFrame ); setAlternatingRowColors( true ); // Enable context menus setContextMenuPolicy( Qt::ActionsContextMenu ); horizontalHeader()->setContextMenuPolicy( Qt::ActionsContextMenu ); setWordWrap( true ); setDragEnabled( true ); // smooth scrolling horizontally, otherwise it tries to jump from item to item. setHorizontalScrollMode( QAbstractItemView::ScrollPerPixel ); d->m_appendEntryAction = new QAction( this ); d->m_actionCollection->addAction( "edit_append", d->m_appendEntryAction ); d->m_actionCollection->setDefaultShortcut( d->m_appendEntryAction, QKeySequence( Qt::Key_Insert ) ); d->m_appendEntryAction->setIcon( QIcon::fromTheme( "list-add-card" ) ); d->m_appendEntryAction->setText( i18n( "&Add New Entry" ) ); connect( d->m_appendEntryAction, SIGNAL( triggered( bool ) ), SLOT( appendEntry() ) ); d->m_appendEntryAction->setShortcut( QKeySequence( Qt::Key_Insert ) ); d->m_appendEntryAction->setWhatsThis( i18n( "Append a new row to the vocabulary" ) ); d->m_appendEntryAction->setToolTip( d->m_appendEntryAction->whatsThis() ); d->m_appendEntryAction->setStatusTip( d->m_appendEntryAction->whatsThis() ); addAction( d->m_appendEntryAction ); d->m_deleteEntriesAction = new QAction( this ); d->m_actionCollection->addAction( "edit_remove_selected_area", d->m_deleteEntriesAction ); d->m_actionCollection->setDefaultShortcut( d->m_deleteEntriesAction, QKeySequence::Delete ); d->m_deleteEntriesAction->setIcon( QIcon::fromTheme( "list-remove-card" ) ); d->m_deleteEntriesAction->setText( i18n( "&Delete Entry" ) ); connect( d->m_deleteEntriesAction, SIGNAL( triggered( bool ) ), this, SLOT( deleteSelectedEntries() ) ); d->m_deleteEntriesAction->setShortcut( QKeySequence::Delete ); d->m_deleteEntriesAction->setWhatsThis( i18n( "Delete the selected rows" ) ); d->m_deleteEntriesAction->setToolTip( d->m_deleteEntriesAction->whatsThis() ); d->m_deleteEntriesAction->setStatusTip( d->m_deleteEntriesAction->whatsThis() ); addAction( d->m_deleteEntriesAction ); QAction* separator = new QAction( this ); separator->setSeparator( true ); addAction( separator ); d->m_copyAction = KStandardAction::copy( this, SLOT( slotEditCopy() ), d->m_actionCollection ); d->m_actionCollection->setDefaultShortcut( d->m_copyAction, QKeySequence::Copy ); d->m_copyAction->setWhatsThis( i18n( "Copy" ) ); d->m_copyAction->setToolTip( d->m_copyAction->whatsThis() ); d->m_copyAction->setStatusTip( d->m_copyAction->whatsThis() ); addAction( d->m_copyAction ); d->m_cutAction = KStandardAction::cut( this, SLOT( slotCutEntry() ), d->m_actionCollection ); d->m_actionCollection->setDefaultShortcut( d->m_cutAction, QKeySequence::Cut ); d->m_cutAction->setWhatsThis( i18n( "Cut" ) ); d->m_cutAction->setToolTip( d->m_cutAction->whatsThis() ); d->m_cutAction->setStatusTip( d->m_cutAction->whatsThis() ); addAction( d->m_cutAction ); d->m_pasteAction = KStandardAction::paste( this, SLOT( slotEditPaste() ), d->m_actionCollection ); d->m_actionCollection->setDefaultShortcut( d->m_pasteAction, QKeySequence::Paste ); d->m_pasteAction->setWhatsThis( i18n( "Paste" ) ); d->m_pasteAction->setToolTip( d->m_pasteAction->whatsThis() ); d->m_pasteAction->setStatusTip( d->m_pasteAction->whatsThis() ); addAction( d->m_pasteAction ); d->m_selectAllAction = KStandardAction::selectAll( this, SLOT( selectAll() ), d->m_actionCollection ); d->m_actionCollection->setDefaultShortcut( d->m_selectAllAction, QKeySequence::SelectAll ); d->m_selectAllAction->setWhatsThis( i18n( "Select all rows" ) ); d->m_selectAllAction->setToolTip( d->m_selectAllAction->whatsThis() ); d->m_selectAllAction->setStatusTip( d->m_selectAllAction->whatsThis() ); d->m_clearSelectionAction = KStandardAction::deselect( this, SLOT( clearSelection() ), d->m_actionCollection ); d->m_actionCollection->setDefaultShortcut( d->m_clearSelectionAction, QKeySequence::Deselect ); d->m_clearSelectionAction->setWhatsThis( i18n( "Deselect all rows" ) ); d->m_clearSelectionAction->setToolTip( d->m_clearSelectionAction->whatsThis() ); d->m_clearSelectionAction->setStatusTip( d->m_clearSelectionAction->whatsThis() ); // vocabulary columns dialog QAction *vocabularyColumnsDialogAction = new QAction( this ); d->m_actionCollection->addAction( "show_vocabulary_columns_dialog", vocabularyColumnsDialogAction ); vocabularyColumnsDialogAction->setIcon( QIcon::fromTheme( "view-file-columns" ) ); vocabularyColumnsDialogAction->setText( i18n( "Vocabulary Columns..." ) ); vocabularyColumnsDialogAction->setWhatsThis( i18n( "Toggle display of individual vocabulary columns" ) ); vocabularyColumnsDialogAction->setToolTip( vocabularyColumnsDialogAction->whatsThis() ); vocabularyColumnsDialogAction->setStatusTip( vocabularyColumnsDialogAction->whatsThis() ); horizontalHeader()->addAction( vocabularyColumnsDialogAction ); addAction( vocabularyColumnsDialogAction ); connect( vocabularyColumnsDialogAction, SIGNAL( triggered( bool ) ), this, SLOT( slotShowVocabularyColumnsDialog() ) ); } KEduVocVocabularyView::~KEduVocVocabularyView() { delete d; } void KEduVocVocabularyView::setAutomaticTranslation( bool automaticTranslation ) { d->m_automaticTranslation = automaticTranslation; } bool KEduVocVocabularyView::automaticTranslation() { return d->m_automaticTranslation; } QList KEduVocVocabularyView::visibleColumns() { return d->m_visibleColumns; } +void KEduVocVocabularyView::setVisibleColumns( QList visibleColumns ) +{ + d->m_visibleColumns = visibleColumns; +} + QByteArray KEduVocVocabularyView::state() { return d->m_state; } void KEduVocVocabularyView::setState( QByteArray state ) { d->m_state = state; } void KEduVocVocabularyView::setSpellCheck( QString spellCheck ) { d->m_spellCheck = spellCheck; } QString KEduVocVocabularyView::spellCheck() { return d->m_spellCheck; } void KEduVocVocabularyView::setFilter( KEduVocVocabularyFilter * model ) { QTableView::setModel( model ); d->m_model = model; connect( selectionModel(), SIGNAL( currentChanged( const QModelIndex &, const QModelIndex & ) ), SLOT( slotCurrentChanged( const QModelIndex &, const QModelIndex & ) ) ); connect( selectionModel(), SIGNAL( selectionChanged( const QItemSelection&, const QItemSelection& ) ), SLOT( slotSelectionChanged( const QItemSelection&, const QItemSelection& ) ) ); slotSelectionChanged( QItemSelection(), QItemSelection() ); } void KEduVocVocabularyView::slotCurrentChanged( const QModelIndex & current, const QModelIndex & previous ) { Q_UNUSED( previous ); KEduVocExpression* entry = 0; if( current.isValid() ) { entry = model()->data( current, KEduVocVocabularyModel::EntryRole ).value(); } emit translationChanged( entry, KEduVocVocabularyModel::translation( current.column() ) ); } void KEduVocVocabularyView::reset( QList visibleColumns, QByteArray state ) { QTableView::reset(); emit translationChanged( 0, 0 ); if ( d->m_doc ) { d->m_visibleColumns = visibleColumns; d->m_state = state; if( !horizontalHeader()->restoreState( state ) ) { resizeColumnsToContents(); } } horizontalHeader()->setSectionsMovable( true ); for( int i = 0; i < model()->columnCount( QModelIndex() ); i++ ) { if( i < visibleColumns.size() ) { setColumnHidden( i, !visibleColumns.value( i ) ); } else { if( KEduVocVocabularyModel::columnType( i ) != KEduVocVocabularyModel::Translation ) { setColumnHidden( i, true ); } } } } void KEduVocVocabularyView::saveColumnVisibility() const { if( !d->m_doc ) { return; } // Generate a QList for saving QList visibleList; for( int i = 0; i < d->m_model->columnCount(); ++i ) { visibleList.append( static_cast( !isColumnHidden( i ) ) ); } d->m_visibleColumns = visibleList; } void KEduVocVocabularyView::appendEntry() { QModelIndex newIndex = d->m_model->appendEntry(); scrollTo( newIndex ); selectionModel()->clear(); // otherwise proxy mapping gets screwed for some reason selectionModel()->select( newIndex, QItemSelectionModel::ClearAndSelect ); selectionModel()->setCurrentIndex( newIndex, QItemSelectionModel::ClearAndSelect ); edit( newIndex ); } void KEduVocVocabularyView::appendChar( const QChar &c ) { const QModelIndex &index = selectionModel()->currentIndex(); d->m_model->setData( index, QString( d->m_model->data( index ).toString() + c ) ); } void KEduVocVocabularyView::deleteSelectedEntries( bool askConfirmation ) { QSet rows; foreach( const QModelIndex & index, selectionModel()->selectedIndexes() ) { rows.insert( index.row() ); } bool del = true; if( askConfirmation ) { del = KMessageBox::Continue == KMessageBox::warningContinueCancel( this, i18np( "Do you really want to delete the selected entry?", "Do you really want to delete the selected %1 entries?", rows.count() ), i18n( "Delete" ), KStandardGuiItem::del() ); } if( del ) { emit translationChanged( 0, 0 ); while( !selectionModel()->selectedIndexes().isEmpty() ) { d->m_model->removeRows( selectionModel()->selectedIndexes()[0].row(), 1, QModelIndex() ); } } } void KEduVocVocabularyView::slotEditCopy() { QModelIndexList sortedIndexes = selectionModel()->selectedIndexes(); qSort( sortedIndexes ); QMimeData *mimeData = d->m_model->mimeData( sortedIndexes ); QClipboard *clipboard = QApplication::clipboard(); clipboard->setMimeData( mimeData ); } void KEduVocVocabularyView::slotEditPaste() { QClipboard *clipboard = QApplication::clipboard(); const QMimeData *mimeData = clipboard->mimeData(); const KEduVocVocabularyMimeData *vocMimeData = qobject_cast( mimeData ); if( vocMimeData ) { qDebug() << "Clipboard contains vocabulary mime data."; foreach( const KEduVocVocabularyMimeData::MimeExpression & mimeEntry, vocMimeData->expressionList() ) { KEduVocExpression *pasteExpression = new KEduVocExpression( mimeEntry.expression ); d->m_model->appendEntry( pasteExpression ); // find word type (create if not found) KEduVocWordType *type = d->m_doc->wordTypeContainer(); foreach( int translation, mimeEntry.wordTypes.keys() ) { // append if needed foreach( const QString & typeName, mimeEntry.wordTypes.value( translation ).wordType ) { qDebug() << mimeEntry.wordTypes.value( translation ).wordType; KEduVocContainer *childType = type->childContainer( typeName ); if( !childType ) { // the doc does not contain the right word type - create it childType = new KEduVocWordType( typeName ); type->appendChildContainer( childType ); } type = static_cast( childType ); } pasteExpression->translation( translation )->setWordType( type ); // check for special type stuff if( type->wordType() != mimeEntry.wordTypes.value( translation ).grammarType ) { if( type->wordType() == KEduVocWordFlag::NoInformation ) { type->setWordType( mimeEntry.wordTypes.value( translation ).grammarType ); } } } } } else if( mimeData->hasText() ) { qDebug() << "Clipboard contains text data."; // split at newline QStringList lines = clipboard->text().split( '\n' ); foreach( QString line, lines ) { // split at tabs or semicolon: d->m_model->appendEntry( new KEduVocExpression( line.split( QRegExp("[\t;]"), QString::KeepEmptyParts ) ) ); } } } void KEduVocVocabularyView::slotCutEntry() { slotEditCopy(); deleteSelectedEntries( false ); } void KEduVocVocabularyView::slotSelectionChanged( const QItemSelection &, const QItemSelection & ) { bool hasSelection = selectionModel()->hasSelection(); d->m_deleteEntriesAction->setEnabled( hasSelection ); d->m_clearSelectionAction->setEnabled( hasSelection ); d->m_copyAction->setEnabled( hasSelection ); d->m_cutAction->setEnabled( hasSelection ); } void KEduVocVocabularyView::setDocument( KEduVocDocument * doc ) { d->m_doc = doc; d->m_vocabularyDelegate->setDocument( doc ); QTimer::singleShot( 0, this, SLOT( reset() ) ); } KEduVocDocument* KEduVocVocabularyView::document() { return d->m_doc; } /** * Set the translator to be used by the delegate * @param translator */ void KEduVocVocabularyView::setTranslator( KEduVocTranslator* translator ) { d->m_vocabularyDelegate->setTranslator( translator ); } -void KEduVocVocabularyView::slotShowVocabularyColumnsDialog( QList visibleColumns, QByteArray state ) +void KEduVocVocabularyView::slotShowVocabularyColumnsDialog() { KEduVocVocabularyColumnsDialog *dialog = new KEduVocVocabularyColumnsDialog( d->m_doc, d->m_visibleColumns, this ); if( dialog->exec() == QDialog::Accepted ) { - reset( visibleColumns, state ); + reset( d->m_visibleColumns, d->m_state ); } } void KEduVocVocabularyView::checkSpelling( int language, QString spellCheck ) { if( !d->m_model->rowCount() ) { KMessageBox::information( this, i18n( "Nothing to spell check." ) ); return; } if( !d->m_spellChecker ) { d->m_spellChecker = new Sonnet::BackgroundChecker( this ); d->m_spellDialog = new Sonnet::Dialog( d->m_spellChecker, this ); connect( d->m_spellDialog, SIGNAL( done( const QString& ) ), this, SLOT( continueSpelling() ) ); connect( d->m_spellDialog, SIGNAL( misspelling( const QString&, int ) ), this, SLOT( misspelling( const QString&, int ) ) ); connect( d->m_spellDialog, SIGNAL( replace( const QString&, int, const QString& ) ), this, SLOT( spellingReplace( const QString&, int, const QString& ) ) ); } d->m_spellColumn = language * KEduVocVocabularyModel::EntryColumnsMAX; d->m_spellRow = -1; if( d->m_spellColumn < 0 ) { return; } d->m_spellCheck = spellCheck; QString locale = d->m_doc->identifier( language ).locale(); QString spellCode = d->m_spellCheck.isEmpty() ? locale : d->m_spellCheck; d->m_spellChecker->changeLanguage( spellCode ); if( !d->m_spellChecker->speller().isValid() ) { qDebug() << "Invalid Language, popup here!"; KNotification::event(KNotification::Warning, i18nc( "@title of a popup", "No Spell Checker Available" ), i18nc( "@popupmessage", "Either the language set up is incorrect or no spellchecker was installed for this locale: %1.", locale ) ); } d->m_spellDialog->show(); continueSpelling(); } void KEduVocVocabularyView::continueSpelling() { qDebug() << "Check spelling: " << d->m_spellRow << d->m_spellColumn; ++d->m_spellRow; while( d->m_spellRow < d->m_model->rowCount() ) { QModelIndex index = d->m_model->index( d->m_spellRow, d->m_spellColumn ); qDebug() << " " << d->m_model->data( index ).toString(); if( !d->m_model->data( index ).toString().isEmpty() ) { d->m_spellDialog->setBuffer( d->m_model->data( index ).toString() ); break; } else { ++d->m_spellRow; } } } void KEduVocVocabularyView::selectIndex( const QModelIndex &newIndex ) { selectionModel()->select( newIndex, QItemSelectionModel::ClearAndSelect ); selectionModel()->setCurrentIndex( newIndex, QItemSelectionModel::ClearAndSelect ); scrollTo( newIndex ); } bool KEduVocVocabularyView::eventFilter( QObject* obj, QEvent* event, bool smartAppend ) { if( event->type() == QEvent::KeyPress && smartAppend ) { QKeyEvent *keyEvent = static_cast( event ); if( keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter ) { if( selectionModel()->currentIndex().row() == d->m_model->rowCount() - 1 ) { appendEntry(); } } } // standard event processing return QObject::eventFilter( obj, event ); } void KEduVocVocabularyView::misspelling( const QString & word, int start ) { Q_UNUSED( word ) Q_UNUSED( start ) QModelIndex index = d->m_model->index( d->m_spellRow, d->m_spellColumn ); selectIndex( index ); } void KEduVocVocabularyView::spellingReplace( const QString & oldWord, int start, const QString & newWord ) { qDebug() << oldWord << start << newWord; QModelIndex index = d->m_model->index( d->m_spellRow, d->m_spellColumn); QString data = index.data().toString(); QString newData = data.replace( start, oldWord.length(), newWord ); qDebug() << "Changing " << data << " to " << newData; d->m_model->setData( index, newData ); } QModelIndexList KEduVocVocabularyView::getSelectedIndexes() const { return selectionModel()->selectedIndexes(); } diff --git a/keduvocdocument/keduvocvocabularyview.h b/keduvocdocument/keduvocvocabularyview.h index a45e65b..ca4b748 100644 --- a/keduvocdocument/keduvocvocabularyview.h +++ b/keduvocdocument/keduvocvocabularyview.h @@ -1,205 +1,188 @@ /*************************************************************************** Copyright 2006, 2007 Peter Hedlund 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. * * * ***************************************************************************/ #ifndef KEDUVOCVOCABULARYVIEW_H #define KEDUVOCVOCABULARYVIEW_H #include // Qt #include #include #include // KDE class KActionCollection; class KActionMenu; class QAction; class QUrl; // KEduVocDocument class KEduVocExpression; class KEduVocDocument; class KEduVocVocabularyFilter; class KEduVocTranslator; namespace Editor { /* FIXME Reimplement this after editor.h is added to keduvoc, and change the constructor accordingly, removing KActionCollection * class EditorWindow; */ class KEduVocVocabularyDelegate; class KEDUVOCDOCUMENT_EXPORT KEduVocVocabularyView : public QTableView { Q_OBJECT public: + /** + * @param automaticTranslation corresponding to Prefs::automaticTranslation() + */ + KEduVocVocabularyView( QWidget *parent, KActionCollection* actionCollection, bool automaticTranslation ); ~KEduVocVocabularyView(); KActionMenu* columnsActionMenu(); void setFilter( KEduVocVocabularyFilter * model ); /** Save column visibility settings * Example Usage: * foo.saveColumnVisibility(); * DocumentSettings ds( foo.document()->url().url() ); * ds.setVisibleColumns( foo.visibleColumns() ); * ds.save(); * * Where foo is a KEduVocVocabularyView object */ void saveColumnVisibility() const; /** Return Column Visibility for model */ QList visibleColumns(); + void setVisibleColumns( QList visibleColumns ); + QModelIndexList getSelectedIndexes() const; /** Set m_automaticTranslation to @param automaticTranslation */ void setAutomaticTranslation( bool automaticTranslation ); /** Return current m_automaticTranslation */ bool automaticTranslation(); QByteArray state(); void setState( QByteArray state ); KEduVocDocument* document(); void setSpellCheck( QString spellCheck ); QString spellCheck(); public slots: /** * @param visibleColumns corresponding to DocumentSettings::visibleColumns() * Example Usage: * DocumentSettings ds( foo.document()->url().url() ); * d s.load(); * visibleColumns = ds.visibleColumns(); * Where foo is a KEduVocVocabularyView object * * @param state * Example Usage (in Parley): * * KConfig parleyConfig("parleyrc"); * KConfigGroup documentGroup(&parleyConfig, "Document " + foo.document()->url().url()); * QByteArray state = documentGroup.readEntry("VocabularyColumns", QByteArray()); * * QByteArray saveState = foo.horizontalHeader()->saveState(); - * KConfig parleyConfig("parleyrc"); - * KConfigGroup documentGroup(&parleyConfig, "Document " + foo.document()->url().url()); * documentGroup.writeEntry("VocabularyColumns", foo.horizontalHeader()->saveState()); * * Where foo is a KEduVocVocabularyView object */ void reset( QList visibleColumns, QByteArray state ); void appendEntry(); /** Delete the currently selected entries */ void deleteSelectedEntries( bool askConfirmation = true ); /** put the marked text/object into the clipboard*/ void slotEditCopy(); /** Cut an entry */ void slotCutEntry(); /** paste the clipboard into the document*/ void slotEditPaste(); /** * Append a char to the last edited entry (used to add the phonetic stuff). * @param c the char */ void appendChar( const QChar & c ); void setDocument( KEduVocDocument * doc ); void setTranslator( KEduVocTranslator* translator ); /** * @param spellCheck corresponding to LanguageSettings::spellChecker * Example Usage: * QString locale = foo.document()->identifier( language ).locale(); * LanguageSettings settings(locale); * QString spellCheck = settings.spellChecker(); */ void checkSpelling( int language, QString spellCheck ); /** * Show the vocabulary columns dialog to enable or disable the columns in the view - * - * @param visibleColumns corresponding to DocumentSettings::visibleColumns() - * Example Usage: - * DocumentSettings ds( foo.document()->url().url() ); - * d s.load(); - * visibleColumns = ds.visibleColumns(); - * Where foo is a KEduVocVocabularyView object - * - * @param state - * Example Usage (in Parley): - * - * KConfig parleyConfig("parleyrc"); - * KConfigGroup documentGroup(&parleyConfig, "Document " + foo.document()->url().url()); - * QByteArray state = documentGroup.readEntry("VocabularyColumns", QByteArray()); - * - * QByteArray saveState = foo.horizontalHeader()->saveState(); - * KConfig parleyConfig("parleyrc"); - * KConfigGroup documentGroup(&parleyConfig, "Document " + foo.document()->url().url()); - * documentGroup.writeEntry("VocabularyColumns", horizontalHeader()->saveState()); - * - * Where foo is a KEduVocVocabularyView object */ - void slotShowVocabularyColumnsDialog( QList visibleColumns, QByteArray state ); + void slotShowVocabularyColumnsDialog(); signals: void translationChanged( KEduVocExpression*, int ); private slots: void slotCurrentChanged( const QModelIndex& current, const QModelIndex& previous ); void slotSelectionChanged( const QItemSelection&, const QItemSelection& ); void continueSpelling(); void misspelling( const QString &word, int start ); void spellingReplace( const QString& oldWord, int start, const QString &newWord ); private: class Private; Private * const d; void selectIndex( const QModelIndex &index ); // trap enter presses at the end of the document to add a new entry instead of moving to the first cell /** * @param smartAppend corresponds to Prefs::smartAppend() */ bool eventFilter( QObject *obj, QEvent *event, bool smartAppend ); // Make this private to avoid inadvertent use. Instead use setFilter() which is public. virtual void setModel( QAbstractItemModel *model ) { Q_UNUSED( model ) } }; } #endif