KDEUI
ktimezonewidget.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (C) 2005, S.R.Haque <srhaque@iee.org>. 00003 Copyright (C) 2009, David Faure <faure@kde.org> 00004 This file is part of the KDE project 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License version 2, as published by the Free Software Foundation. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00021 #include "ktimezonewidget.h" 00022 00023 #include <QtCore/QFile> 00024 #include <QtGui/QPixmap> 00025 00026 #include <kdebug.h> 00027 #include <klocale.h> 00028 #include <kstandarddirs.h> 00029 #include <ksystemtimezone.h> 00030 #include <ktimezone.h> 00031 00032 class KTimeZoneWidget::Private 00033 { 00034 public: 00035 Private() : itemsCheckable(false), singleSelection(true) {} 00036 00037 enum Columns 00038 { 00039 CityColumn = 0, 00040 RegionColumn, 00041 CommentColumn 00042 }; 00043 00044 enum Roles 00045 { 00046 ZoneRole = Qt::UserRole + 0xF3A3CB1 00047 }; 00048 00049 bool itemsCheckable; 00050 bool singleSelection; 00051 }; 00052 00053 #ifndef KDE_USE_FINAL 00054 static bool localeLessThan (const QString &a, const QString &b) 00055 { 00056 return QString::localeAwareCompare(a, b) < 0; 00057 } 00058 #endif 00059 00060 KTimeZoneWidget::KTimeZoneWidget( QWidget *parent, KTimeZones *db ) 00061 : QTreeWidget( parent ), 00062 d(new KTimeZoneWidget::Private) 00063 { 00064 // If the user did not provide a timezone database, we'll use the system default. 00065 setRootIsDecorated(false); 00066 setHeaderLabels( QStringList() << i18nc("Define an area in the time zone, like a town area", "Area" ) << i18nc( "Time zone", "Region" ) << i18n( "Comment" ) ); 00067 00068 // Collect zones by localized city names, so that they can be sorted properly. 00069 QStringList cities; 00070 QHash<QString, KTimeZone> zonesByCity; 00071 00072 if (!db) { 00073 db = KSystemTimeZones::timeZones(); 00074 00075 // add UTC to the defaults default 00076 KTimeZone utc = KTimeZone::utc(); 00077 cities.append(utc.name()); 00078 zonesByCity.insert(utc.name(), utc); 00079 } 00080 00081 const KTimeZones::ZoneMap zones = db->zones(); 00082 for ( KTimeZones::ZoneMap::ConstIterator it = zones.begin(); it != zones.end(); ++it ) { 00083 const KTimeZone zone = it.value(); 00084 const QString continentCity = displayName( zone ); 00085 const int separator = continentCity.lastIndexOf('/'); 00086 // Make up the localized key that will be used for sorting. 00087 // Example: i18n(Asia/Tokyo) -> key = "i18n(Tokyo)|i18n(Asia)|Asia/Tokyo" 00088 // The zone name is appended to ensure unicity even with equal translations (#174918) 00089 const QString key = continentCity.mid(separator+1) + '|' 00090 + continentCity.left(separator) + '|' + zone.name(); 00091 cities.append( key ); 00092 zonesByCity.insert( key, zone ); 00093 } 00094 qSort( cities.begin(), cities.end(), localeLessThan ); 00095 00096 foreach ( const QString &key, cities ) { 00097 const KTimeZone zone = zonesByCity.value(key); 00098 const QString tzName = zone.name(); 00099 QString comment = zone.comment(); 00100 00101 if ( !comment.isEmpty() ) 00102 comment = i18n( comment.toUtf8() ); 00103 00104 // Convert: 00105 // 00106 // "Europe/London", "GB" -> "London", "Europe/GB". 00107 // "UTC", "" -> "UTC", "". 00108 QStringList continentCity = displayName( zone ).split( '/' ); 00109 00110 QTreeWidgetItem *listItem = new QTreeWidgetItem( this ); 00111 listItem->setText( Private::CityColumn, continentCity[ continentCity.count() - 1 ] ); 00112 QString countryName = KGlobal::locale()->countryCodeToName( zone.countryCode() ); 00113 if ( countryName.isEmpty() ) { 00114 continentCity[ continentCity.count() - 1 ] = zone.countryCode(); 00115 } else { 00116 continentCity[ continentCity.count() - 1 ] = countryName; 00117 } 00118 00119 listItem->setText( Private::RegionColumn, continentCity.join( QChar('/') ) ); 00120 listItem->setText( Private::CommentColumn, comment ); 00121 listItem->setData( Private::CityColumn, Private::ZoneRole, tzName ); // store complete path in custom role 00122 00123 // Locate the flag from /l10n/%1/flag.png. 00124 QString flag = KStandardDirs::locate( "locale", QString( "l10n/%1/flag.png" ).arg( zone.countryCode().toLower() ) ); 00125 if ( QFile::exists( flag ) ) 00126 listItem->setIcon( Private::RegionColumn, QPixmap( flag ) ); 00127 } 00128 } 00129 00130 KTimeZoneWidget::~KTimeZoneWidget() 00131 { 00132 delete d; 00133 } 00134 00135 void KTimeZoneWidget::setItemsCheckable(bool enable) 00136 { 00137 d->itemsCheckable = enable; 00138 const int count = topLevelItemCount(); 00139 for (int row = 0; row < count; ++row) { 00140 QTreeWidgetItem* listItem = topLevelItem(row); 00141 listItem->setCheckState(Private::CityColumn, Qt::Unchecked); 00142 } 00143 QTreeWidget::setSelectionMode(QAbstractItemView::NoSelection); 00144 } 00145 00146 bool KTimeZoneWidget::itemsCheckable() const 00147 { 00148 return d->itemsCheckable; 00149 } 00150 00151 QString KTimeZoneWidget::displayName( const KTimeZone &zone ) 00152 { 00153 return i18n( zone.name().toUtf8() ).replace( '_', ' ' ); 00154 } 00155 00156 QStringList KTimeZoneWidget::selection() const 00157 { 00158 QStringList selection; 00159 00160 // Loop through all entries. 00161 // Do not use selectedItems() because it skips hidden items, making it 00162 // impossible to use a KTreeWidgetSearchLine. 00163 // There is no QTreeWidgetItemConstIterator, hence the const_cast :/ 00164 QTreeWidgetItemIterator it(const_cast<KTimeZoneWidget*>(this), d->itemsCheckable ? QTreeWidgetItemIterator::Checked : QTreeWidgetItemIterator::Selected); 00165 for (; *it; ++it) { 00166 selection.append( (*it)->data( Private::CityColumn, Private::ZoneRole ).toString() ); 00167 } 00168 00169 return selection; 00170 } 00171 00172 void KTimeZoneWidget::setSelected( const QString &zone, bool selected ) 00173 { 00174 bool found = false; 00175 00176 // The code was using findItems( zone, Qt::MatchExactly, Private::ZoneColumn ) 00177 // previously, but the underlying model only has 3 columns, the "hidden" column 00178 // wasn't available in there. 00179 00180 if (!d->itemsCheckable) { 00181 // Runtime compatibility for < 4.3 apps, which don't call the setMultiSelection reimplementation. 00182 d->singleSelection = (QTreeWidget::selectionMode() == QAbstractItemView::SingleSelection); 00183 } 00184 00185 // Loop through all entries. 00186 const int rowCount = model()->rowCount(QModelIndex()); 00187 for (int row = 0; row < rowCount; ++row) { 00188 const QModelIndex index = model()->index(row, Private::CityColumn); 00189 const QString tzName = index.data(Private::ZoneRole).toString(); 00190 if (tzName == zone) { 00191 00192 if (d->singleSelection && selected) { 00193 clearSelection(); 00194 } 00195 00196 if (d->itemsCheckable) { 00197 QTreeWidgetItem* listItem = itemFromIndex(index); 00198 listItem->setCheckState(Private::CityColumn, selected ? Qt::Checked : Qt::Unchecked); 00199 } else { 00200 selectionModel()->select(index, selected ? (QItemSelectionModel::Select | QItemSelectionModel::Rows) : (QItemSelectionModel::Deselect | QItemSelectionModel::Rows)); 00201 } 00202 00203 // Ensure the selected item is visible as appropriate. 00204 scrollTo( index ); 00205 00206 found = true; 00207 00208 if (d->singleSelection && selected) { 00209 break; 00210 } 00211 } 00212 } 00213 00214 if ( !found ) 00215 kDebug() << "No such zone: " << zone; 00216 } 00217 00218 void KTimeZoneWidget::clearSelection() 00219 { 00220 if (d->itemsCheckable) { 00221 // Un-select all items 00222 const int rowCount = model()->rowCount(QModelIndex()); 00223 for (int row = 0; row < rowCount; ++row) { 00224 const QModelIndex index = model()->index(row, 0); 00225 QTreeWidgetItem* listItem = itemFromIndex(index); 00226 listItem->setCheckState(Private::CityColumn, Qt::Unchecked); 00227 } 00228 } else { 00229 QTreeWidget::clearSelection(); 00230 } 00231 } 00232 00233 void KTimeZoneWidget::setSelectionMode(QAbstractItemView::SelectionMode mode) 00234 { 00235 d->singleSelection = (mode == QAbstractItemView::SingleSelection); 00236 if (!d->itemsCheckable) { 00237 QTreeWidget::setSelectionMode(mode); 00238 } 00239 } 00240 00241 QAbstractItemView::SelectionMode KTimeZoneWidget::selectionMode() const 00242 { 00243 if (d->itemsCheckable) { 00244 return d->singleSelection ? QTreeWidget::SingleSelection : QTreeWidget::MultiSelection; 00245 } else { 00246 return QTreeWidget::selectionMode(); 00247 } 00248 } 00249 00250 #include "ktimezonewidget.moc"
KDE 4.6 API Reference