mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-24 10:52:51 +00:00
366 lines
11 KiB
C++
366 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 <QKeyEvent>
|
||
|
#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);
|
||
|
|
||
|
const QString &sub = QString::fromLatin1("l10n/");
|
||
|
|
||
|
QStringList regionlist = KGlobal::dirs()->findAllResources("locale",
|
||
|
sub + QString::fromLatin1("*.desktop"),
|
||
|
KStandardDirs::NoDuplicates);
|
||
|
|
||
|
QFontMetrics fm(lv1->font());
|
||
|
int lv1Width = 0;
|
||
|
|
||
|
foreach(const QString ®ion, 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("*/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 ¤t = 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 ¤t = 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 ¤t = 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 ¤t)
|
||
|
{
|
||
|
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();
|
||
|
}
|