goldendict-ng/src/ui/orderandprops.cc

303 lines
9.8 KiB
C++

/* This file is (c) 2008-2012 Konstantin Isakov <ikm@goldendict.org>
* Part of GoldenDict. Licensed under GPLv3 or later, see the LICENSE file */
#include "orderandprops.hh"
#include "instances.hh"
#include "langcoder.hh"
#include "language.hh"
#include <algorithm>
#include <utility>
#include <QMenu>
using std::vector;
using std::sort;
namespace {
bool dictNameLessThan( sptr< Dictionary::Class > const & dict1, sptr< Dictionary::Class > const & dict2 )
{
QString str1 = QString::fromUtf8( dict1->getName().c_str() );
QString str2 = QString::fromUtf8( dict2->getName().c_str() );
if ( str1.isEmpty() && !str2.isEmpty() ) {
return false;
}
if ( !str1.isEmpty() && str2.isEmpty() ) {
return true;
}
return str1.localeAwareCompare( str2 ) < 0;
}
bool dictLessThan( sptr< Dictionary::Class > const & dict1, sptr< Dictionary::Class > const & dict2 )
{
int idFrom1 = dict1->getLangFrom();
int idTo1 = dict1->getLangTo();
if ( idFrom1 == 0 ) {
std::pair< quint32, quint32 > ids =
LangCoder::findLangIdPairFromName( QString::fromUtf8( dict1->getName().c_str() ) );
idFrom1 = ids.first;
idTo1 = ids.second;
}
int idFrom2 = dict2->getLangFrom();
int idTo2 = dict2->getLangTo();
if ( idFrom2 == 0 ) {
std::pair< quint32, quint32 > ids =
LangCoder::findLangIdPairFromName( QString::fromUtf8( dict2->getName().c_str() ) );
idFrom2 = ids.first;
idTo2 = ids.second;
}
QString str1 = LangCoder::decode( idFrom1 );
QString str2 = LangCoder::decode( idFrom2 );
if ( str1.isEmpty() && !str2.isEmpty() ) {
return false;
}
if ( !str1.isEmpty() && str2.isEmpty() ) {
return true;
}
int res = str1.localeAwareCompare( str2 );
if ( res ) {
return res < 0;
}
str1 = LangCoder::decode( idTo1 );
str2 = LangCoder::decode( idTo2 );
if ( str1.isEmpty() && !str2.isEmpty() ) {
return false;
}
if ( !str1.isEmpty() && str2.isEmpty() ) {
return true;
}
res = str1.localeAwareCompare( str2 );
if ( res ) {
return res < 0;
}
str1 = QString::fromUtf8( dict1->getName().c_str() );
str2 = QString::fromUtf8( dict2->getName().c_str() );
if ( str1.isEmpty() && !str2.isEmpty() ) {
return false;
}
if ( !str1.isEmpty() && str2.isEmpty() ) {
return true;
}
return str1.localeAwareCompare( str2 ) < 0;
}
} // namespace
OrderAndProps::OrderAndProps( QWidget * parent,
Config::Group const & dictionaryOrder,
Config::Group const & inactiveDictionaries,
std::vector< sptr< Dictionary::Class > > const & allDictionaries ):
QWidget( parent )
{
ui.setupUi( this );
Instances::Group order( dictionaryOrder, allDictionaries, Config::Group() );
Instances::Group inactive( inactiveDictionaries, allDictionaries, Config::Group() );
Instances::complementDictionaryOrder( order, inactive, allDictionaries );
ui.dictionaryOrder->populate( order.dictionaries, allDictionaries );
ui.inactiveDictionaries->populate( inactive.dictionaries, allDictionaries );
ui.searchLine->applyTo( ui.dictionaryOrder );
addAction( ui.searchLine->getFocusAction() );
disableDictionaryDescription();
ui.dictionaryOrder->setContextMenuPolicy( Qt::CustomContextMenu );
connect( ui.dictionaryOrder, &QWidget::customContextMenuRequested, this, &OrderAndProps::contextMenuRequested );
connect( ui.dictionaryOrder, &DictListWidget::gotFocus, this, &OrderAndProps::dictListFocused );
connect( ui.inactiveDictionaries, &DictListWidget::gotFocus, this, &OrderAndProps::inactiveDictListFocused );
connect( ui.dictionaryOrder->selectionModel(),
&QItemSelectionModel::selectionChanged,
this,
&OrderAndProps::dictionarySelectionChanged );
connect( ui.inactiveDictionaries->selectionModel(),
&QItemSelectionModel::selectionChanged,
this,
&OrderAndProps::inactiveDictionarySelectionChanged );
connect( ui.searchLine, &QuickFilterLine::filterChanged, this, &OrderAndProps::filterChanged );
connect( ui.dictionaryOrder->getModel(), &DictListModel::contentChanged, this, &OrderAndProps::showDictNumbers );
connect( ui.inactiveDictionaries->getModel(), &DictListModel::contentChanged, this, &OrderAndProps::showDictNumbers );
showDictNumbers();
}
Config::Group OrderAndProps::getCurrentDictionaryOrder() const
{
Instances::Group g( "" );
g.dictionaries = ui.dictionaryOrder->getCurrentDictionaries();
return g.makeConfigGroup();
}
Config::Group OrderAndProps::getCurrentInactiveDictionaries() const
{
Instances::Group g( "" );
g.dictionaries = ui.inactiveDictionaries->getCurrentDictionaries();
return g.makeConfigGroup();
}
void OrderAndProps::filterChanged( QString const & filterText )
{
// when the filter is active, disable the possibility
// to drop dictionaries to this filtered list
ui.dictionaryOrder->setAcceptDrops( filterText.isEmpty() );
}
void OrderAndProps::dictListFocused()
{
describeDictionary( ui.dictionaryOrder, ui.searchLine->mapToSource( ui.dictionaryOrder->currentIndex() ) );
}
void OrderAndProps::inactiveDictListFocused()
{
describeDictionary( ui.inactiveDictionaries, ui.inactiveDictionaries->currentIndex() );
}
void OrderAndProps::dictionarySelectionChanged( const QItemSelection & current, const QItemSelection & deselected )
{
Q_UNUSED( deselected )
if ( current.empty() ) {
return;
}
describeDictionary( ui.dictionaryOrder, ui.searchLine->mapToSource( current.front().topLeft() ) );
}
void OrderAndProps::inactiveDictionarySelectionChanged( QItemSelection const & current )
{
if ( current.empty() ) {
return;
}
describeDictionary( ui.inactiveDictionaries, current.front().topLeft() );
}
void OrderAndProps::disableDictionaryDescription()
{
ui.dictionaryInformation->setEnabled( false );
ui.dictionaryName->clear();
ui.dictionaryTotalArticles->clear();
ui.dictionaryTotalWords->clear();
ui.dictionaryTranslatesFrom->clear();
ui.dictionaryTranslatesTo->clear();
ui.dictionaryFileList->clear();
ui.dictionaryDescription->clear();
ui.dictionaryDescription->setVisible( false );
ui.dictionaryDescriptionLabel->setVisible( false );
ui.infoVerticalSpacer->changeSize( 20, 5, QSizePolicy::Minimum, QSizePolicy::Expanding );
ui.infoVerticalLayout->invalidate();
}
void OrderAndProps::describeDictionary( DictListWidget * lst, QModelIndex const & idx )
{
if ( !idx.isValid() || (unsigned)idx.row() >= lst->getCurrentDictionaries().size() ) {
disableDictionaryDescription();
}
else {
sptr< Dictionary::Class > dict = lst->getCurrentDictionaries()[ idx.row() ];
if ( !dict ) {
return;
}
ui.dictionaryInformation->setEnabled( true );
ui.dictionaryName->setText( QString::fromUtf8( dict->getName().c_str() ) );
ui.dictionaryTotalArticles->setText( QString::number( dict->getArticleCount() ) );
ui.dictionaryTotalWords->setText( QString::number( dict->getWordCount() ) );
ui.dictionaryTranslatesFrom->setText( Language::localizedStringForId( dict->getLangFrom() ) );
ui.dictionaryTranslatesTo->setText( Language::localizedStringForId( dict->getLangTo() ) );
std::vector< std::string > const & filenames = dict->getDictionaryFilenames();
QString filenamesText;
for ( unsigned x = 0; x < filenames.size(); x++ ) {
filenamesText += filenames[ x ].c_str();
filenamesText += '\n';
}
ui.dictionaryFileList->setPlainText( filenamesText );
QString descText = dict->getDescription();
if ( !descText.isEmpty() && descText.compare( "NONE" ) != 0 ) {
//qtbug QTBUG-112020
descText.remove( QRegularExpression( R"(<link[^>]*>)", QRegularExpression::CaseInsensitiveOption ) );
ui.dictionaryDescription->setHtml( descText );
ui.dictionaryDescription->setVisible( true );
ui.dictionaryDescriptionLabel->setVisible( true );
ui.infoVerticalSpacer->changeSize( 0, 0, QSizePolicy::Minimum, QSizePolicy::Minimum );
}
else {
ui.dictionaryDescription->setVisible( false );
ui.dictionaryDescriptionLabel->setVisible( false );
ui.infoVerticalSpacer->changeSize( 20, 5, QSizePolicy::Minimum, QSizePolicy::Expanding );
}
ui.infoVerticalLayout->invalidate();
}
}
void OrderAndProps::contextMenuRequested( const QPoint & pos )
{
QMenu menu( this );
QAction * showHeadwordsAction = NULL;
QModelIndex idx = ui.searchLine->mapToSource( ui.dictionaryOrder->indexAt( pos ) );
sptr< Dictionary::Class > dict;
if ( idx.isValid() && (unsigned)idx.row() < ui.dictionaryOrder->getCurrentDictionaries().size() ) {
dict = ui.dictionaryOrder->getCurrentDictionaries()[ idx.row() ];
}
if ( dict && dict->getWordCount() > 0 ) {
showHeadwordsAction = new QAction( tr( "Dictionary headwords" ), &menu );
menu.addAction( showHeadwordsAction );
}
QAction * sortNameAction = new QAction( tr( "Sort by name" ), &menu );
menu.addAction( sortNameAction );
QAction * sortLangAction = new QAction( tr( "Sort by languages" ), &menu );
menu.addAction( sortLangAction );
QAction * result = menu.exec( ui.dictionaryOrder->mapToGlobal( pos ) );
if ( result == sortNameAction || result == sortLangAction ) {
vector< sptr< Dictionary::Class > > sortedDicts = ui.dictionaryOrder->getCurrentDictionaries();
if ( result == sortNameAction ) {
sort( sortedDicts.begin(), sortedDicts.end(), dictNameLessThan );
}
else {
sort( sortedDicts.begin(), sortedDicts.end(), dictLessThan );
}
ui.dictionaryOrder->populate( sortedDicts );
}
if ( result && result == showHeadwordsAction ) {
emit showDictionaryHeadwords( dict.get() );
}
}
void OrderAndProps::showDictNumbers()
{
ui.dictionariesNumber->setText(
tr( "Dictionaries active: %1, inactive: %2" )
.arg( QString::number( ui.dictionaryOrder->getModel()->rowCount( QModelIndex() ) ) )
.arg( QString::number( ui.inactiveDictionaries->getModel()->rowCount( QModelIndex() ) ) ) );
}