kde-workspace/kcontrol/locale/countryselectordialog.cpp
Ivailo Monev 84a7f988cc kcontrol: avoid temporary in CountrySelectorDialog::editCountry()
Signed-off-by: Ivailo Monev <xakepa10@laimg.moc>
2020-02-02 16:19:27 +00:00

363 lines
11 KiB
C++

/***************************************************************************
* Copyright (C) 2007 by Albert Astals Cid <aacid@kde.org> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
***************************************************************************/
#include "countryselectordialog.h"
#include "kcontrollocale.h"
#include <KStandardDirs>
#include <QAbstractItemModel>
#include <QHBoxLayout>
#include <QtGui/qevent.h>
#include <QListView>
#include <QScrollBar>
struct CountryModelItem
{
CountryModelItem()
{
}
CountryModelItem( CountryModelItem *p, const QString &theText, const QString &theTag )
: parent(p), text(theText), tag(theTag)
{
}
~CountryModelItem()
{
qDeleteAll(children);
}
int row() const
{
if (parent) return parent->children.indexOf(const_cast<CountryModelItem*>(this));
return 0;
}
CountryModelItem *parent;
QList< CountryModelItem* > children;
QString text, tag;
KIcon icon;
};
bool CountryModelItemLessThan(CountryModelItem *s1, CountryModelItem *s2)
{
return s1->text < s2->text;
}
class CountryModel : public QAbstractItemModel
{
public:
CountryModel(QObject *parent) : QAbstractItemModel(parent)
{
m_rootItem = new CountryModelItem(NULL, QString(), QString());
}
CountryModel(CountryModelItem *rootItem, QObject *parent) : QAbstractItemModel(parent)
{
m_rootItem = rootItem;
}
~CountryModel()
{
if (m_rootItem->parent == NULL) delete m_rootItem;
}
void addRegion(const QString &name, const QString &tag)
{
CountryModelItem *cmi = new CountryModelItem(m_rootItem, name, tag);
m_rootItem->children.append(cmi);
}
void addSubRegion(const KIcon &flag, const QString &name, const QString &tag, const QString &superRegion)
{
CountryModelItem *parent = NULL;
foreach(CountryModelItem *cm, m_rootItem->children)
{
if (cm->tag == superRegion) parent = cm;
}
if (parent)
{
CountryModelItem *cmi = new CountryModelItem(parent, name, tag);
cmi->icon = flag;
parent->children.append(cmi);
}
}
void sort()
{
qSort(m_rootItem->children.begin(), m_rootItem->children.end(), CountryModelItemLessThan);
foreach(CountryModelItem *cm, m_rootItem->children)
{
qSort(cm->children.begin(), cm->children.end(), CountryModelItemLessThan);
}
}
int rowCount(const QModelIndex &parent) const
{
if (parent.column() > 0)
return 0;
CountryModelItem *parentItem;
if (!parent.isValid())
parentItem = m_rootItem;
else
parentItem = static_cast<CountryModelItem*>(parent.internalPointer());
return parentItem->children.count();
}
int columnCount(const QModelIndex &parent) const
{
if (!parent.isValid()) return 1;
else
{
CountryModelItem *p = static_cast<CountryModelItem*>(parent.internalPointer());
if (p->parent) return 1;
else return 0;
}
}
QModelIndex index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
CountryModelItem *parentItem;
if (!parent.isValid())
parentItem = m_rootItem;
else
parentItem = static_cast<CountryModelItem*>(parent.internalPointer());
CountryModelItem *childItem = parentItem->children.at(row);
if (childItem)
return createIndex(row, column, childItem);
else
return QModelIndex();
}
QModelIndex parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
CountryModelItem *childItem = static_cast<CountryModelItem*>(index.internalPointer());
CountryModelItem *parentItem = childItem->parent;
if (parentItem == m_rootItem)
return QModelIndex();
return createIndex(parentItem->row(), 0, parentItem);
}
QVariant data(const QModelIndex &index, int role) const
{
if (index.isValid())
{
CountryModelItem *cmi = static_cast<CountryModelItem*>(index.internalPointer());
if (role == Qt::DisplayRole)
{
return cmi->text;
}
else if (role == Qt::DecorationRole)
{
if (cmi->parent->parent) return cmi->icon;
}
}
return QVariant();
}
private:
CountryModelItem *m_rootItem;
};
class CSDListView : public QListView
{
public:
CSDListView(QWidget *parent) : QListView(parent)
{
}
void setOtherWidget(QWidget *widget, Qt::Key key)
{
m_other = widget;
m_key = key;
}
protected:
void keyPressEvent(QKeyEvent *event)
{
if (event->key() == m_key) m_other->setFocus();
else QListView::keyPressEvent(event);
}
private:
QWidget *m_other;
Qt::Key m_key;
};
CountrySelectorDialog::CountrySelectorDialog(QWidget *parent) : KDialog(parent)
{
setCaption( i18n("Country Selector") );
setButtons( KDialog::Ok | KDialog::Cancel );
QWidget *widget = new QWidget(this);
setMainWidget(widget);
}
bool CountrySelectorDialog::editCountry(KControlLocale *locale)
{
QHBoxLayout *hbl = new QHBoxLayout(mainWidget());
CSDListView *lv1 = new CSDListView(mainWidget());
m_countriesView = new CSDListView(mainWidget());
hbl->addWidget(lv1);
hbl->addWidget(m_countriesView);
lv1->setOtherWidget(m_countriesView, Qt::Key_Right);
m_countriesView->setOtherWidget(lv1, Qt::Key_Left);
QString country, region;
country = locale->country();
CountryModel *cm = new CountryModel(this);
QStringList regionlist = KGlobal::dirs()->findAllResources("locale",
QString::fromLatin1("l10n/*.desktop"),
KStandardDirs::NoDuplicates);
QFontMetrics fm(lv1->font());
int lv1Width = 0;
foreach(const QString &region, regionlist)
{
QString tag = region;
int index;
index = tag.lastIndexOf('/');
if (index != -1)
tag = tag.mid(index + 1);
index = tag.lastIndexOf('.');
if (index != -1)
tag.truncate(index);
KConfig entry(region);
KConfigGroup cg = entry.group("KCM Locale");
QString name = cg.readEntry("Name", ki18n("without name").toString(locale));
cm->addRegion(name, tag);
QString spacedName = name + " ";
lv1Width = qMax(lv1Width, fm.width(spacedName));
}
// add all languages to the list
QStringList countrylist = KGlobal::dirs()->findAllResources("locale",
sub + QString::fromLatin1("l10n/*/entry.desktop"),
KStandardDirs::NoDuplicates);
foreach(const QString &countryFile, countrylist)
{
KConfig entry(countryFile);
KConfigGroup cg = entry.group("KCM Locale");
QString name = cg.readEntry("Name", ki18n("without name").toString(locale));
QString parentRegion = cg.readEntry("Region");
QString tag = countryFile;
int index = tag.lastIndexOf('/');
tag.truncate(index);
index = tag.lastIndexOf('/');
tag = tag.mid(index + 1);
QString flag( KStandardDirs::locate( "locale", QString::fromLatin1( "l10n/%1/flag.png" ).arg(tag) ) );
cm->addSubRegion(KIcon(flag), name, tag, parentRegion);
if (tag == country) region = parentRegion;
}
cm->sort();
cm->addRegion(i18nc("@item:inlistbox Country", "Not set (Generic English)"), "C");
if (country == "C") region = "C";
lv1->setModel(cm);
lv1->setFixedWidth(lv1Width + lv1->verticalScrollBar()->height());
// + 2 because 1 is "Not set (Generic English)" and the other is for spacing
lv1->setMinimumHeight((regionlist.count() + 2) * fm.height());
connect(lv1->selectionModel(), SIGNAL(currentChanged(const QModelIndex &, const QModelIndex &)), SLOT(regionChanged(const QModelIndex &)));
connect(lv1, SIGNAL(activated(const QModelIndex &)), SLOT(regionActivated()));
connect(m_countriesView, SIGNAL(activated(const QModelIndex &)), SLOT(accept()));
for(int i = 0; i < lv1->model()->rowCount(); ++i)
{
const QModelIndex &current = lv1->model()->index(i, 0);
CountryModelItem *cmi = static_cast<CountryModelItem*>(current.internalPointer());
if (cmi->tag == region)
{
lv1->selectionModel()->setCurrentIndex(current, QItemSelectionModel::SelectCurrent);
}
}
if (m_countriesView->model() != NULL)
{
for(int i = 0; i < m_countriesView->model()->rowCount(); ++i)
{
const QModelIndex &current = m_countriesView->model()->index(i, 0);
CountryModelItem *cmi = static_cast<CountryModelItem*>(current.internalPointer());
if (cmi->tag == country)
{
m_countriesView->selectionModel()->setCurrentIndex(current, QItemSelectionModel::SelectCurrent);
}
}
m_countriesView->setFocus();
}
else lv1->setFocus();
if (exec() == QDialog::Accepted)
{
const QModelIndex &current = m_countriesView->currentIndex();
if (current.isValid())
{
CountryModelItem *cmi = static_cast<CountryModelItem*>(current.internalPointer());
return locale->setCountry(cmi->tag);
}
else if (m_countriesView->model() == NULL)
{
return locale->setCountry("C");
}
}
return false;
}
void CountrySelectorDialog::regionChanged(const QModelIndex &current)
{
delete m_countriesView->model();
CountryModelItem *cmi = static_cast<CountryModelItem*>(current.internalPointer());
if (!cmi->children.isEmpty())
{
CountryModel *cm = new CountryModel(cmi, this);
m_countriesView->setModel(cm);
}
else
{
m_countriesView->setModel(NULL);
}
}
void CountrySelectorDialog::regionActivated()
{
if (m_countriesView->model() != NULL) m_countriesView->setFocus();
else accept();
}