add more spacing
[personal-kdebase.git] / runtime / kcontrol / locale / countryselectordialog.cpp
blob9e1344de0890af55f86060f795ae15ace5d4ac74
1 /***************************************************************************
2 * Copyright (C) 2007 by Albert Astals Cid <aacid@kde.org> *
3 * *
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>
18 #include <QKeyEvent>
19 #include <QListView>
20 #include <QScrollBar>
22 struct CountryModelItem
24 CountryModelItem()
28 CountryModelItem( CountryModelItem *p, const QString &theText, const QString &theTag )
29 : parent(p), text(theText), tag(theTag)
33 ~CountryModelItem()
35 qDeleteAll(children);
38 int row() const
40 if (parent) return parent->children.indexOf(const_cast<CountryModelItem*>(this));
41 return 0;
44 CountryModelItem *parent;
45 QList< CountryModelItem* > children;
47 QString text, tag;
48 KIcon icon;
53 bool CountryModelItemLessThan(CountryModelItem *s1, CountryModelItem *s2)
55 return s1->text < s2->text;
60 class CountryModel : public QAbstractItemModel
62 public:
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;
73 ~CountryModel()
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;
91 if (parent)
93 CountryModelItem *cmi = new CountryModelItem(parent, name, tag);
94 cmi->icon = flag;
95 parent->children.append(cmi);
99 void sort()
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)
111 return 0;
113 CountryModelItem *parentItem;
114 if (!parent.isValid())
115 parentItem = m_rootItem;
116 else
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;
125 else
127 CountryModelItem *p = static_cast<CountryModelItem*>(parent.internalPointer());
128 if (p->parent) return 1;
129 else return 0;
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;
141 else
142 parentItem = static_cast<CountryModelItem*>(parent.internalPointer());
144 CountryModelItem *childItem = parentItem->children.at(row);
145 if (childItem)
146 return createIndex(row, column, childItem);
147 else
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
167 if (index.isValid())
169 CountryModelItem *cmi = static_cast<CountryModelItem*>(index.internalPointer());
170 if (role == Qt::DisplayRole)
172 return cmi->text;
174 else if (role == Qt::DecorationRole)
176 if (cmi->parent->parent) return cmi->icon;
179 return QVariant();
182 private:
183 CountryModelItem *m_rootItem;
188 class CSDListView : public QListView
190 public:
191 CSDListView(QWidget *parent) : QListView(parent)
195 void setOtherWidget(QWidget *widget, Qt::Key key)
197 m_other = widget;
198 m_key = key;
201 protected:
202 void keyPressEvent(QKeyEvent *event)
204 if (event->key() == m_key) m_other->setFocus();
205 else QListView::keyPressEvent(event);
208 private:
209 QWidget *m_other;
210 Qt::Key m_key;
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());
229 hbl->addWidget(lv1);
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());
246 int lv1Width = 0;
248 foreach(const QString &region, regionlist)
250 QString tag = region;
251 int index;
253 index = tag.lastIndexOf('/');
254 if (index != -1)
255 tag = tag.mid(index + 1);
257 index = tag.lastIndexOf('.');
258 if (index != -1)
259 tag.truncate(index);
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('/');
283 tag.truncate(index);
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;
292 cm->sort();
294 cm->addRegion(i18nc("@item:inlistbox Country", "Not set (Generic English)"), "C");
295 if (country == "C") region = "C";
297 lv1->setModel(cm);
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 &current = 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 &current = 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 &current = 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");
343 return false;
346 void CountrySelectorDialog::regionChanged(const QModelIndex &current)
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);
355 else
357 m_countriesView->setModel(NULL);
361 void CountrySelectorDialog::regionActivated()
363 if (m_countriesView->model() != NULL) m_countriesView->setFocus();
364 else accept();