1 /***************************************************************************
2 * Copyright (C) 2007 by Albert Astals Cid <aacid@kde.org> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 ***************************************************************************/
10 #include "countryselectordialog.h"
12 #include "kcontrollocale.h"
14 #include <KStandardDirs>
16 #include <QAbstractItemModel>
17 #include <QHBoxLayout>
22 struct CountryModelItem
28 CountryModelItem( CountryModelItem
*p
, const QString
&theText
, const QString
&theTag
)
29 : parent(p
), text(theText
), tag(theTag
)
40 if (parent
) return parent
->children
.indexOf(const_cast<CountryModelItem
*>(this));
44 CountryModelItem
*parent
;
45 QList
< CountryModelItem
* > children
;
53 bool CountryModelItemLessThan(CountryModelItem
*s1
, CountryModelItem
*s2
)
55 return s1
->text
< s2
->text
;
60 class CountryModel
: public QAbstractItemModel
63 CountryModel(QObject
*parent
) : QAbstractItemModel(parent
)
65 m_rootItem
= new CountryModelItem(NULL
, QString(), QString());
68 CountryModel(CountryModelItem
*rootItem
, QObject
*parent
) : QAbstractItemModel(parent
)
70 m_rootItem
= rootItem
;
75 if (m_rootItem
->parent
== NULL
) delete m_rootItem
;
78 void addRegion(const QString
&name
, const QString
&tag
)
80 CountryModelItem
*cmi
= new CountryModelItem(m_rootItem
, name
, tag
);
81 m_rootItem
->children
.append(cmi
);
84 void addSubRegion(const KIcon
&flag
, const QString
&name
, const QString
&tag
, const QString
&superRegion
)
86 CountryModelItem
*parent
= NULL
;
87 foreach(CountryModelItem
*cm
, m_rootItem
->children
)
89 if (cm
->tag
== superRegion
) parent
= cm
;
93 CountryModelItem
*cmi
= new CountryModelItem(parent
, name
, tag
);
95 parent
->children
.append(cmi
);
101 qSort(m_rootItem
->children
.begin(), m_rootItem
->children
.end(), CountryModelItemLessThan
);
102 foreach(CountryModelItem
*cm
, m_rootItem
->children
)
104 qSort(cm
->children
.begin(), cm
->children
.end(), CountryModelItemLessThan
);
108 int rowCount(const QModelIndex
&parent
) const
110 if (parent
.column() > 0)
113 CountryModelItem
*parentItem
;
114 if (!parent
.isValid())
115 parentItem
= m_rootItem
;
117 parentItem
= static_cast<CountryModelItem
*>(parent
.internalPointer());
119 return parentItem
->children
.count();
122 int columnCount(const QModelIndex
&parent
) const
124 if (!parent
.isValid()) return 1;
127 CountryModelItem
*p
= static_cast<CountryModelItem
*>(parent
.internalPointer());
128 if (p
->parent
) return 1;
133 QModelIndex
index(int row
, int column
, const QModelIndex
&parent
) const
135 if (!hasIndex(row
, column
, parent
))
136 return QModelIndex();
138 CountryModelItem
*parentItem
;
139 if (!parent
.isValid())
140 parentItem
= m_rootItem
;
142 parentItem
= static_cast<CountryModelItem
*>(parent
.internalPointer());
144 CountryModelItem
*childItem
= parentItem
->children
.at(row
);
146 return createIndex(row
, column
, childItem
);
148 return QModelIndex();
151 QModelIndex
parent(const QModelIndex
&index
) const
153 if (!index
.isValid())
154 return QModelIndex();
156 CountryModelItem
*childItem
= static_cast<CountryModelItem
*>(index
.internalPointer());
157 CountryModelItem
*parentItem
= childItem
->parent
;
159 if (parentItem
== m_rootItem
)
160 return QModelIndex();
162 return createIndex(parentItem
->row(), 0, parentItem
);
165 QVariant
data(const QModelIndex
&index
, int role
) const
169 CountryModelItem
*cmi
= static_cast<CountryModelItem
*>(index
.internalPointer());
170 if (role
== Qt::DisplayRole
)
174 else if (role
== Qt::DecorationRole
)
176 if (cmi
->parent
->parent
) return cmi
->icon
;
183 CountryModelItem
*m_rootItem
;
188 class CSDListView
: public QListView
191 CSDListView(QWidget
*parent
) : QListView(parent
)
195 void setOtherWidget(QWidget
*widget
, Qt::Key key
)
202 void keyPressEvent(QKeyEvent
*event
)
204 if (event
->key() == m_key
) m_other
->setFocus();
205 else QListView::keyPressEvent(event
);
215 CountrySelectorDialog::CountrySelectorDialog(QWidget
*parent
) : KDialog(parent
)
217 setCaption( i18n("Country Selector") );
218 setButtons( KDialog::Ok
| KDialog::Cancel
);
220 QWidget
*widget
= new QWidget(this);
221 setMainWidget(widget
);
224 bool CountrySelectorDialog::editCountry(KControlLocale
*locale
)
226 QHBoxLayout
*hbl
= new QHBoxLayout(mainWidget());
227 CSDListView
*lv1
= new CSDListView(mainWidget());
228 m_countriesView
= new CSDListView(mainWidget());
230 hbl
->addWidget(m_countriesView
);
231 lv1
->setOtherWidget(m_countriesView
, Qt::Key_Right
);
232 m_countriesView
->setOtherWidget(lv1
, Qt::Key_Left
);
234 QString country
, region
;
235 country
= locale
->country();
237 CountryModel
*cm
= new CountryModel(this);
239 const QString
&sub
= QString::fromLatin1("l10n/");
241 QStringList regionlist
= KGlobal::dirs()->findAllResources("locale",
242 sub
+ QString::fromLatin1("*.desktop"),
243 KStandardDirs::NoDuplicates
);
245 QFontMetrics
fm(lv1
->font());
248 foreach(const QString
®ion
, regionlist
)
250 QString tag
= region
;
253 index
= tag
.lastIndexOf('/');
255 tag
= tag
.mid(index
+ 1);
257 index
= tag
.lastIndexOf('.');
261 KConfig
entry(region
);
262 KConfigGroup cg
= entry
.group("KCM Locale");
263 QString name
= cg
.readEntry("Name", ki18n("without name").toString(locale
));
265 cm
->addRegion(name
, tag
);
266 QString spacedName
= name
+ " ";
267 lv1Width
= qMax(lv1Width
, fm
.width(spacedName
));
270 // add all languages to the list
271 QStringList countrylist
= KGlobal::dirs()->findAllResources("locale",
272 sub
+ QString::fromLatin1("*/entry.desktop"),
273 KStandardDirs::NoDuplicates
);
274 foreach(const QString
&countryFile
, countrylist
)
276 KConfig
entry(countryFile
);
277 KConfigGroup cg
= entry
.group("KCM Locale");
278 QString name
= cg
.readEntry("Name", ki18n("without name").toString(locale
));
279 QString parentRegion
= cg
.readEntry("Region");
281 QString tag
= countryFile
;
282 int index
= tag
.lastIndexOf('/');
284 index
= tag
.lastIndexOf('/');
285 tag
= tag
.mid(index
+ 1);
287 QString
flag( KStandardDirs::locate( "locale", QString::fromLatin1( "l10n/%1/flag.png" ).arg(tag
) ) );
288 cm
->addSubRegion(KIcon(flag
), name
, tag
, parentRegion
);
289 if (tag
== country
) region
= parentRegion
;
294 cm
->addRegion(i18nc("@item:inlistbox Country", "Not set (Generic English)"), "C");
295 if (country
== "C") region
= "C";
298 lv1
->setFixedWidth(lv1Width
+ lv1
->verticalScrollBar()->height());
299 // + 2 because 1 is "Not set (Generic English)" and the other is for spacing
300 lv1
->setMinimumHeight((regionlist
.count() + 2) * fm
.height());
302 connect(lv1
->selectionModel(), SIGNAL(currentChanged(const QModelIndex
&, const QModelIndex
&)), SLOT(regionChanged(const QModelIndex
&)));
303 connect(lv1
, SIGNAL(activated(const QModelIndex
&)), SLOT(regionActivated()));
304 connect(m_countriesView
, SIGNAL(activated(const QModelIndex
&)), SLOT(accept()));
306 for(int i
= 0; i
< lv1
->model()->rowCount(); ++i
)
308 const QModelIndex
¤t
= lv1
->model()->index(i
, 0);
309 CountryModelItem
*cmi
= static_cast<CountryModelItem
*>(current
.internalPointer());
310 if (cmi
->tag
== region
)
312 lv1
->selectionModel()->setCurrentIndex(current
, QItemSelectionModel::SelectCurrent
);
315 if (m_countriesView
->model() != NULL
)
317 for(int i
= 0; i
< m_countriesView
->model()->rowCount(); ++i
)
319 const QModelIndex
¤t
= m_countriesView
->model()->index(i
, 0);
320 CountryModelItem
*cmi
= static_cast<CountryModelItem
*>(current
.internalPointer());
321 if (cmi
->tag
== country
)
323 m_countriesView
->selectionModel()->setCurrentIndex(current
, QItemSelectionModel::SelectCurrent
);
326 m_countriesView
->setFocus();
328 else lv1
->setFocus();
330 if (exec() == QDialog::Accepted
)
332 const QModelIndex
¤t
= m_countriesView
->currentIndex();
333 if (current
.isValid())
335 CountryModelItem
*cmi
= static_cast<CountryModelItem
*>(current
.internalPointer());
336 return locale
->setCountry(cmi
->tag
);
338 else if (m_countriesView
->model() == NULL
)
340 return locale
->setCountry("C");
346 void CountrySelectorDialog::regionChanged(const QModelIndex
¤t
)
348 delete m_countriesView
->model();
349 CountryModelItem
*cmi
= static_cast<CountryModelItem
*>(current
.internalPointer());
350 if (!cmi
->children
.isEmpty())
352 CountryModel
*cm
= new CountryModel(cmi
, this);
353 m_countriesView
->setModel(cm
);
357 m_countriesView
->setModel(NULL
);
361 void CountrySelectorDialog::regionActivated()
363 if (m_countriesView
->model() != NULL
) m_countriesView
->setFocus();