• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

libkleo

  • sources
  • kde-4.12
  • kdepim
  • libkleo
  • ui
directoryserviceswidget.cpp
Go to the documentation of this file.
1 /*
2  directoryserviceswidget.cpp
3 
4  This file is part of Kleopatra, the KDE keymanager
5  Copyright (c) 2001,2002,2004 Klar�vdalens Datakonsult AB
6 
7  Kleopatra is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  Kleopatra is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21  In addition, as a special exception, the copyright holders give
22  permission to link the code of this program with any edition of
23  the Qt library by Trolltech AS, Norway (or with modified versions
24  of Qt that use the same license as Qt), and distribute linked
25  combinations including the two. You must obey the GNU General
26  Public License in all respects for all of the code used other than
27  Qt. If you modify this file, you may extend this exception to
28  your version of the file, but you are not obligated to do so. If
29  you do not wish to do so, delete this exception statement from
30  your version.
31 */
32 
33 #include "directoryserviceswidget.h"
34 
35 #include "ui_directoryserviceswidget.h"
36 
37 #include <KIcon>
38 #include <KDebug>
39 
40 #include <QItemDelegate>
41 #include <QAbstractTableModel>
42 #include <QSpinBox>
43 #include <QComboBox>
44 #include <QHeaderView>
45 #include <QMenu>
46 #include <QAction>
47 
48 #include <boost/bind.hpp>
49 
50 #include <vector>
51 
52 #include <climits>
53 #include <cassert>
54 #include <algorithm>
55 #include <functional>
56 
57 using namespace Kleo;
58 using namespace boost;
59 
60 namespace {
61 
62  static KUrl defaultX509Service() {
63  KUrl url;
64  url.setScheme( QLatin1String("ldap") );
65  url.setHost( i18nc("default server name, keep it a valid domain name, ie. no spaces", "server") );
66  return url;
67  }
68  static KUrl defaultOpenPGPService() {
69  KUrl url;
70  url.setScheme( QLatin1String("hkp") );
71  url.setHost( QLatin1String("keys.gnupg.net") );
72  return url;
73  }
74 
75  static bool is_ldap_scheme( const KUrl & url ) {
76  const QString scheme = url.protocol();
77  return QString::compare( scheme, QLatin1String( "ldap" ), Qt::CaseInsensitive ) == 0
78  || QString::compare( scheme, QLatin1String( "ldaps" ), Qt::CaseInsensitive ) == 0;
79  }
80 
81  static const struct {
82  const char label[6];
83  unsigned short port;
84  DirectoryServicesWidget::Scheme base;
85  } protocols[] = {
86  { I18N_NOOP("hkp"), 11371, DirectoryServicesWidget::HKP },
87  { I18N_NOOP("http"), 80, DirectoryServicesWidget::HTTP },
88  { I18N_NOOP("https"), 443, DirectoryServicesWidget::HTTP },
89  { I18N_NOOP("ftp"), 21, DirectoryServicesWidget::FTP },
90  { I18N_NOOP("ftps"), 990, DirectoryServicesWidget::FTP },
91  { I18N_NOOP("ldap"), 389, DirectoryServicesWidget::LDAP },
92  { I18N_NOOP("ldaps"), 636, DirectoryServicesWidget::LDAP },
93  };
94  static const unsigned int numProtocols = sizeof protocols / sizeof *protocols;
95 
96  static unsigned short default_port( const QString & scheme ) {
97  for ( unsigned int i = 0 ; i < numProtocols ; ++i )
98  if ( QString::compare( scheme, QLatin1String( protocols[i].label ), Qt::CaseInsensitive ) == 0 )
99  return protocols[i].port;
100  return 0;
101  }
102 
103  static QString display_scheme( const KUrl & url ) {
104  if ( url.scheme().isEmpty() )
105  return QLatin1String( "hkp" );
106  else
107  return url.scheme();
108  }
109 
110  static QString display_host( const KUrl & url ) {
111  // work around "subkeys.pgp.net" being interpreted as a path, not host
112  if ( url.host().isEmpty() )
113  return url.path();
114  else
115  return url.host();
116  }
117 
118  static unsigned short display_port( const KUrl & url ) {
119  if ( url.port() > 0 )
120  return url.port();
121  else
122  return default_port( display_scheme( url ) );
123  }
124 
125  static bool is_default_port( const KUrl & url ) {
126  return display_port( url ) == default_port( display_scheme( url ) ) ;
127  }
128 
129  static QRect calculate_geometry( const QRect & cell, const QSize & sizeHint ) {
130  const int height = qMax( cell.height(), sizeHint.height() );
131  return QRect( cell.left(), cell.top() - ( height - cell.height() ) / 2,
132  cell.width(), height );
133  }
134 
135  struct KUrl_compare : std::binary_function<KUrl,KUrl,bool> {
136  bool operator()( const KUrl & lhs, const KUrl & rhs ) const {
137  return QString::compare( display_scheme( lhs ), display_scheme( rhs ), Qt::CaseInsensitive ) == 0
138  && QString::compare( display_host( lhs ), display_host( rhs ), Qt::CaseInsensitive ) == 0
139  && lhs.port() == rhs.port()
140  && lhs.user() == rhs.user()
141  // ... ignore password...
142  && ( !is_ldap_scheme( lhs )
143  || KUrl::fromPercentEncoding( lhs.query().mid( 1 ).toLatin1() )
144  == KUrl::fromPercentEncoding( rhs.query().mid( 1 ).toLatin1() ) ) ;
145  }
146  };
147 
148  class Model : public QAbstractTableModel {
149  Q_OBJECT
150  public:
151  explicit Model( QObject * parent=0 )
152  : QAbstractTableModel( parent ),
153  m_items(),
154  m_openPGPReadOnly( false ),
155  m_x509ReadOnly( false ),
156  m_schemes( DirectoryServicesWidget::AllSchemes )
157  {
158 
159  }
160 
161  void setOpenPGPReadOnly( bool ro ) {
162  if ( ro == m_openPGPReadOnly )
163  return;
164  m_openPGPReadOnly = ro;
165  for ( unsigned int row = 0, end = rowCount() ; row != end ; ++row )
166  if ( isOpenPGPService( row ) )
167  emit dataChanged( index( row, 0 ), index( row, NumColumns ) );
168  }
169 
170  void setX509ReadOnly( bool ro ) {
171  if ( ro == m_x509ReadOnly )
172  return;
173  m_x509ReadOnly = ro;
174  for ( unsigned int row = 0, end = rowCount() ; row != end ; ++row )
175  if ( isX509Service( row ) )
176  emit dataChanged( index( row, 0 ), index( row, NumColumns ) );
177  }
178 
179  QModelIndex addOpenPGPService( const KUrl & url, bool force=false ) {
180  return addService( url, false, true, force );
181  }
182  QModelIndex addX509Service( const KUrl & url, bool force=false ) {
183  return addService( url, true, false, force );
184  }
185  QModelIndex addService( const KUrl & url, bool x509, bool pgp, bool force ) {
186  const std::vector<Item>::iterator it = force ? m_items.end() : findExistingUrl( url ) ;
187  unsigned int row;
188  if ( it != m_items.end() ) {
189  // existing item:
190  it->x509 |= x509;
191  it->pgp |= pgp;
192  row = it - m_items.begin() ;
193  emit dataChanged( index( row, std::min( X509, OpenPGP ) ), index( row, std::max( X509, OpenPGP ) ) );
194  } else {
195  // append new item
196  const Item item = { url, x509, pgp };
197  row = m_items.size();
198  beginInsertRows( QModelIndex(), row, row );
199  m_items.push_back( item );
200  endInsertRows();
201  }
202  return index( row, firstEditableColumn( row ) );
203  }
204 
205  unsigned int numServices() const { return m_items.size(); }
206  bool isOpenPGPService( unsigned int row ) const { return row < m_items.size() && m_items[row].pgp; }
207  bool isX509Service( unsigned int row ) const { return row < m_items.size() && m_items[row].x509 && isLdapRow( row ) ; }
208  KUrl service( unsigned int row ) const { return row < m_items.size() ? m_items[row].url : KUrl() ; }
209 
210  bool isReadOnlyRow( unsigned int row ) const {
211  return ( isX509Service( row ) && m_x509ReadOnly )
212  || ( isOpenPGPService( row ) && m_openPGPReadOnly );
213  }
214 
215  enum Columns {
216  Scheme,
217  Host,
218  Port,
219  BaseDN,
220  UserName,
221  Password,
222  X509,
223  OpenPGP,
224 
225  NumColumns
226  };
227 
228  QModelIndex duplicateRow( unsigned int row ) {
229  if ( row >= m_items.size() )
230  return QModelIndex();
231 
232  beginInsertRows( QModelIndex(), row+1, row+1 );
233  m_items.insert( m_items.begin() + row + 1, m_items[row] );
234  if ( m_items[row].pgp )
235  m_items[row+1].pgp = false; // enforce pgp exclusivitiy
236  endInsertRows();
237  return index( row+1, 0 );
238  }
239 
240  void deleteRow( unsigned int row ) {
241  if ( row >= m_items.size() )
242  return;
243 
244  beginRemoveRows( QModelIndex(), row, row );
245  m_items.erase( m_items.begin() + row );
246  endInsertRows();
247  }
248 
249  void clear() {
250  if ( m_items.empty() )
251  return;
252  beginRemoveRows( QModelIndex(), 0, m_items.size()-1 );
253  m_items.clear();
254  endRemoveRows();
255  }
256 
257  /* reimp */ int columnCount( const QModelIndex & =QModelIndex() ) const { return NumColumns; }
258  /* reimp */ int rowCount( const QModelIndex & =QModelIndex() ) const { return m_items.size(); }
259 
260  /* reimp */ QVariant data( const QModelIndex & idx, int role ) const;
261  /* reimp */ QVariant headerData( int section, Qt::Orientation o, int role ) const;
262 
263  /* reimp */ Qt::ItemFlags flags( const QModelIndex & idx ) const;
264  /* reimp */ bool setData( const QModelIndex & idx, const QVariant & value, int role );
265 
266  private:
267  bool doSetData( unsigned int row, unsigned int column, const QVariant & value, int role );
268  void setExclusivePgpFlag( unsigned int row );
269 
270  static QString toolTipForColumn( int column );
271  bool isLdapRow( unsigned int row ) const;
272  int firstEditableColumn( unsigned int ) const {
273  return Host;
274  }
275 
276  private:
277  struct Item {
278  KUrl url;
279  bool x509 : 1;
280  bool pgp : 1;
281  };
282  std::vector<Item> m_items;
283  bool m_openPGPReadOnly : 1;
284  bool m_x509ReadOnly : 1;
285  DirectoryServicesWidget::Schemes m_schemes;
286 
287  private:
288  std::vector<Item>::iterator findExistingUrl( const KUrl & url ) {
289  return std::find_if( m_items.begin(), m_items.end(),
290  boost::bind( KUrl_compare(), url, boost::bind( &Item::url, _1 ) ) );
291  }
292  };
293 
294  class Delegate : public QItemDelegate {
295  Q_OBJECT
296  public:
297  explicit Delegate( QObject * parent=0 )
298  : QItemDelegate( parent ),
299  m_schemes( DirectoryServicesWidget::AllSchemes )
300  {
301 
302  }
303 
304  void setAllowedSchemes( const DirectoryServicesWidget::Schemes schemes ) {
305  m_schemes = schemes;
306  }
307  DirectoryServicesWidget::Schemes allowedSchemes() const { return m_schemes; }
308 
309  /* reimp */
310  QWidget * createEditor( QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & idx ) const {
311  switch ( idx.column() ) {
312  case Model::Scheme:
313  return createSchemeWidget( parent );
314  case Model::Port:
315  return createPortWidget( parent );
316  }
317  return QItemDelegate::createEditor( parent, option, idx );
318  }
319 
320  /* reimp */
321  void setEditorData( QWidget * editor, const QModelIndex & idx ) const {
322  switch ( idx.column() ) {
323  case Model::Scheme:
324  setSchemeEditorData( qobject_cast<QComboBox*>( editor ), idx.data( Qt::EditRole ).toString() );
325  break;
326  case Model::Port:
327  setPortEditorData( qobject_cast<QSpinBox*>( editor ), idx.data( Qt::EditRole ).toInt() );
328  break;
329  default:
330  QItemDelegate::setEditorData( editor, idx );
331  break;
332  }
333  }
334 
335  /* reimp */
336  void setModelData( QWidget * editor, QAbstractItemModel * model, const QModelIndex & idx ) const {
337  switch ( idx.column() ) {
338  case Model::Scheme:
339  setSchemeModelData( qobject_cast<QComboBox*>( editor ), model, idx );
340  break;
341  case Model::Port:
342  setPortModelData( qobject_cast<QSpinBox*>( editor ), model, idx );
343  break;
344  default:
345  QItemDelegate::setModelData( editor, model, idx );
346  break;
347  }
348  }
349 
350  /* reimp */
351  void updateEditorGeometry( QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index ) const {
352  if ( index.column() == Model::Scheme || index.column() == Model::Port )
353  editor->setGeometry( calculate_geometry( option.rect, editor->sizeHint() ) );
354  else
355  QItemDelegate::updateEditorGeometry( editor, option, index );
356  }
357 
358  private:
359  QWidget * createSchemeWidget( QWidget * parent ) const {
360  if ( !m_schemes )
361  return 0;
362  QComboBox * cb = new QComboBox( parent );
363  for ( unsigned int i = 0 ; i < numProtocols ; ++i )
364  if ( m_schemes & protocols[i].base )
365  cb->addItem( i18n( protocols[i].label ), QLatin1String(protocols[i].label) );
366  assert( cb->count() > 0 );
367  return cb;
368  }
369  void setSchemeEditorData( QComboBox * cb, const QString & scheme ) const {
370  assert( cb );
371  cb->setCurrentIndex( cb->findData( scheme, Qt::UserRole, Qt::MatchFixedString ) );
372  }
373  void setSchemeModelData( const QComboBox * cb, QAbstractItemModel * model, const QModelIndex & idx ) const {
374  assert( cb );
375  assert( model );
376  model->setData( idx, cb->itemData( cb->currentIndex() ) );
377  }
378 
379  QWidget * createPortWidget( QWidget * parent ) const {
380  QSpinBox * sb = new QSpinBox( parent );
381  sb->setRange( 1, USHRT_MAX ); // valid port numbers
382  return sb;
383  }
384  void setPortEditorData( QSpinBox * sb, unsigned short port ) const {
385  assert( sb );
386  sb->setValue( port );
387  }
388  void setPortModelData( const QSpinBox * sb, QAbstractItemModel * model, const QModelIndex & idx ) const {
389  assert( sb );
390  assert( model );
391  model->setData( idx, sb->value() );
392  }
393 
394  private:
395  DirectoryServicesWidget::Schemes m_schemes;
396  };
397 
398 }
399 
400 class DirectoryServicesWidget::Private {
401  friend class ::Kleo::DirectoryServicesWidget;
402  DirectoryServicesWidget * const q;
403 public:
404  explicit Private( DirectoryServicesWidget * qq )
405  : q( qq ),
406  protocols( AllProtocols ),
407  readOnlyProtocols( NoProtocol ),
408  model(),
409  delegate(),
410  ui( q )
411  {
412  ui.treeView->setModel( &model );
413  ui.treeView->setItemDelegate( &delegate );
414 
415  connect( &model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
416  q, SIGNAL(changed()) );
417  connect( &model, SIGNAL(rowsInserted(QModelIndex,int,int)),
418  q, SIGNAL(changed()) );
419  connect( &model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
420  q, SIGNAL(changed()) );
421  connect( ui.treeView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
422  q, SLOT(slotSelectionChanged()) );
423 
424  slotShowUserAndPasswordToggled( false );
425  }
426 
427 private:
428  void slotNewClicked() {
429  int row = selectedRow();
430  if ( row < 0 )
431  row = currentRow();
432  if ( row < 0 || model.isReadOnlyRow( row ) )
433  if ( protocols & OpenPGPProtocol )
434  slotNewOpenPGPClicked();
435  else if ( protocols & X509Protocol )
436  slotNewX509Clicked();
437  else
438  assert( !"This should not happen.");
439  else
440  edit( model.duplicateRow( row ) );
441  }
442  void edit( const QModelIndex & index ) {
443  if ( index.isValid() ) {
444  ui.treeView->clearSelection();
445  ui.treeView->selectionModel()->setCurrentIndex( index, QItemSelectionModel::Select|QItemSelectionModel::Rows );
446  ui.treeView->edit( index );
447  }
448  }
449  void slotNewX509Clicked() {
450  edit( model.addX509Service( defaultX509Service(), true ) );
451  }
452  void slotNewOpenPGPClicked() {
453  edit( model.addOpenPGPService( defaultOpenPGPService(), true ) );
454  }
455  void slotDeleteClicked() {
456  model.deleteRow( selectedRow() );
457  }
458  void slotSelectionChanged() {
459  enableDisableActions();
460  }
461  void slotShowUserAndPasswordToggled( bool on ) {
462  QHeaderView * const hv = ui.treeView->header();
463  assert( hv );
464  hv->setSectionHidden( Model::UserName, !on );
465  hv->setSectionHidden( Model::Password, !on );
466  }
467 
468  int selectedRow() const {
469  const QModelIndexList mil = ui.treeView->selectionModel()->selectedRows();
470  return mil.empty() ? -1 : mil.front().row();
471  }
472  int currentRow() const {
473  const QModelIndex idx = ui.treeView->selectionModel()->currentIndex();
474  return idx.isValid() ? idx.row() : -1 ;
475  }
476 
477  void showHideColumns();
478 
479  void enableDisableActions() {
480  const bool x509 = ( protocols & X509Protocol ) && !( readOnlyProtocols & X509Protocol ) ;
481  const bool pgp = ( protocols & OpenPGPProtocol ) && !( readOnlyProtocols & OpenPGPProtocol ) ;
482  ui.newX509Action.setEnabled( x509 );
483  ui.newOpenPGPAction.setEnabled( pgp );
484  if ( x509 && pgp ) {
485  ui.newTB->setMenu( &ui.newMenu );
486  ui.newTB->setPopupMode( QToolButton::MenuButtonPopup );
487  } else {
488  ui.newTB->setMenu( 0 );
489  ui.newTB->setPopupMode( QToolButton::DelayedPopup );
490  ui.newTB->setEnabled( x509 || pgp );
491  }
492  const int row = selectedRow();
493  ui.deleteTB->setEnabled( row >= 0 && !model.isReadOnlyRow( row ) );
494  }
495 
496 private:
497  Protocols protocols;
498  Protocols readOnlyProtocols;
499  Model model;
500  Delegate delegate;
501  struct UI : Ui_DirectoryServicesWidget {
502  QAction newX509Action;
503  QAction newOpenPGPAction;
504  QMenu newMenu;
505 
506  explicit UI( DirectoryServicesWidget * q )
507  : Ui_DirectoryServicesWidget(),
508  newX509Action( i18nc("New X.509 Directory Server", "X.509"), q ),
509  newOpenPGPAction( i18nc("New OpenPGP Directory Server", "OpenPGP"), q ),
510  newMenu( q )
511  {
512  newX509Action.setObjectName( QLatin1String("newX509Action") );
513  newOpenPGPAction.setObjectName( QLatin1String("newOpenPGPAction") );
514  newMenu.setObjectName( QLatin1String("newMenu") );
515 
516  setupUi( q );
517 
518  connect( &newX509Action, SIGNAL(triggered()), q, SLOT(slotNewX509Clicked()) );
519  connect( &newOpenPGPAction, SIGNAL(triggered()), q, SLOT(slotNewOpenPGPClicked()) );
520 
521  newMenu.addAction( &newX509Action );
522  newMenu.addAction( &newOpenPGPAction );
523 
524  newTB->setMenu( &newMenu );
525  }
526 
527  } ui;
528 };
529 
530 DirectoryServicesWidget::DirectoryServicesWidget( QWidget * p, Qt::WindowFlags f )
531  : QWidget( p, f ), d( new Private( this ) )
532 {
533 
534 }
535 
536 
537 DirectoryServicesWidget::~DirectoryServicesWidget() {
538  delete d;
539 }
540 
541 void DirectoryServicesWidget::setAllowedSchemes( Schemes schemes ) {
542  d->delegate.setAllowedSchemes( schemes );
543  d->showHideColumns();
544 }
545 
546 DirectoryServicesWidget::Schemes DirectoryServicesWidget::allowedSchemes() const {
547  return d->delegate.allowedSchemes();
548 }
549 
550 void DirectoryServicesWidget::setAllowedProtocols( Protocols protocols ) {
551  if ( d->protocols == protocols )
552  return;
553  d->protocols = protocols;
554  d->showHideColumns();
555  d->enableDisableActions();
556 }
557 
558 DirectoryServicesWidget::Protocols DirectoryServicesWidget::allowedProtocols() const {
559  return d->protocols;
560 }
561 
562 void DirectoryServicesWidget::setReadOnlyProtocols( Protocols protocols ) {
563  if ( d->readOnlyProtocols == protocols )
564  return;
565  d->readOnlyProtocols = protocols;
566  d->model.setOpenPGPReadOnly( protocols & OpenPGPProtocol );
567  d->model.setX509ReadOnly( protocols & X509Protocol );
568  d->enableDisableActions();
569 }
570 
571 DirectoryServicesWidget::Protocols DirectoryServicesWidget::readOnlyProtocols() const {
572  return d->readOnlyProtocols;
573 }
574 
575 void DirectoryServicesWidget::addOpenPGPServices( const KUrl::List & urls ) {
576  Q_FOREACH( const KUrl & url, urls )
577  d->model.addOpenPGPService( url );
578 }
579 
580 KUrl::List DirectoryServicesWidget::openPGPServices() const {
581  KUrl::List result;
582  for ( unsigned int i = 0, end = d->model.numServices() ; i != end ; ++i )
583  if ( d->model.isOpenPGPService( i ) )
584  result.push_back( d->model.service( i ) );
585  return result;
586 }
587 
588 void DirectoryServicesWidget::addX509Services( const KUrl::List & urls ) {
589  Q_FOREACH( const KUrl & url, urls )
590  d->model.addX509Service( url );
591 }
592 
593 KUrl::List DirectoryServicesWidget::x509Services() const {
594  KUrl::List result;
595  for ( unsigned int i = 0, end = d->model.numServices() ; i != end ; ++i )
596  if ( d->model.isX509Service( i ) )
597  result.push_back( d->model.service( i ) );
598  return result;
599 }
600 
601 void DirectoryServicesWidget::clear() {
602  if ( !d->model.numServices() )
603  return;
604  d->model.clear();
605  emit changed();
606 }
607 
608 void DirectoryServicesWidget::Private::showHideColumns() {
609  QHeaderView * const hv = ui.treeView->header();
610  assert( hv );
611  // don't show 'scheme' column when only accepting X509Protocol (###?)
612  hv->setSectionHidden( Model::Scheme, protocols == X509Protocol );
613  // hide the protocol selection columns for if only one protocol is allowed anyway:
614  hv->setSectionHidden( Model::X509, protocols != AllProtocols );
615  hv->setSectionHidden( Model::OpenPGP, protocols != AllProtocols );
616 }
617 
618 //
619 // Model
620 //
621 
622 QVariant Model::headerData( int section, Qt::Orientation orientation, int role ) const {
623  if ( orientation == Qt::Horizontal )
624  if ( role == Qt::ToolTipRole )
625  return toolTipForColumn( section );
626  else if ( role == Qt::DisplayRole )
627  switch ( section ) {
628  case Scheme: return i18n("Scheme");
629  case Host: return i18n("Server Name");
630  case Port: return i18n("Server Port");
631  case BaseDN: return i18n("Base DN");
632  case UserName: return i18n("User Name");
633  case Password: return i18n("Password");
634  case X509: return i18n("X.509");
635  case OpenPGP: return i18n("OpenPGP");
636  default: return QVariant();
637  }
638  else
639  return QVariant();
640  else
641  return QAbstractTableModel::headerData( section, orientation, role );
642 }
643 
644 QVariant Model::data( const QModelIndex & index, int role ) const {
645  const unsigned int row = index.row();
646  if ( index.isValid() && row < m_items.size() )
647  switch ( role ) {
648  case Qt::ToolTipRole: {
649  const QString tt = toolTipForColumn( index.column() );
650  if ( !isReadOnlyRow( index.row() ) )
651  return tt;
652  else
653  return tt.isEmpty()
654  ? i18n("(read-only)")
655  : i18nc("amended tooltip; %1: original tooltip",
656  "%1 (read-only)", tt );
657  }
658  case Qt::DisplayRole:
659  case Qt::EditRole:
660  switch ( index.column() ) {
661  case Scheme:
662  return display_scheme( m_items[row].url );
663  case Host:
664  return display_host( m_items[row].url );
665  case Port:
666  return display_port( m_items[row].url );
667  case BaseDN:
668  if ( isLdapRow( row ) )
669  return KUrl::fromPercentEncoding( m_items[row].url.query().mid( 1 ).toLatin1() ); // decode query and skip leading '?'
670  else
671  return QVariant();
672  case UserName:
673  return m_items[row].url.user();
674  case Password:
675  return m_items[row].url.pass();
676  case X509:
677  case OpenPGP:
678  default:
679  return QVariant();
680  }
681  case Qt::CheckStateRole:
682  switch ( index.column() ) {
683  case X509:
684  return m_items[row].x509 && isLdapRow( row ) ? Qt::Checked : Qt::Unchecked ;
685  case OpenPGP:
686  return m_items[row].pgp ? Qt::Checked : Qt::Unchecked ;
687  default:
688  return QVariant();
689  }
690  }
691  return QVariant();
692 }
693 
694 bool Model::isLdapRow( unsigned int row ) const {
695  if ( row >= m_items.size() )
696  return false;
697  return is_ldap_scheme( m_items[row].url );
698 }
699 
700 Qt::ItemFlags Model::flags( const QModelIndex & index ) const {
701  const unsigned int row = index.row();
702  Qt::ItemFlags flags = QAbstractTableModel::flags( index );
703  if ( isReadOnlyRow( row ) )
704  flags &= ~Qt::ItemIsSelectable ;
705  if ( index.isValid() && row < m_items.size() )
706  switch ( index.column() ) {
707  case Scheme:
708  switch ( m_schemes ) {
709  default:
710  if ( !isReadOnlyRow( row ) )
711  return flags | Qt::ItemIsEditable ;
712  // else fall through
713  case DirectoryServicesWidget::HKP:
714  case DirectoryServicesWidget::HTTP:
715  case DirectoryServicesWidget::FTP:
716  case DirectoryServicesWidget::LDAP:
717  // only one scheme allowed -> no editing possible
718  return flags & ~(Qt::ItemIsEditable|Qt::ItemIsEnabled) ;
719  }
720  case Host:
721  case Port:
722  if ( isReadOnlyRow( row ) )
723  return flags & ~(Qt::ItemIsEditable|Qt::ItemIsEnabled) ;
724  else
725  return flags | Qt::ItemIsEditable ;
726  case BaseDN:
727  if ( isLdapRow( row ) && !isReadOnlyRow( row ) )
728  return flags | Qt::ItemIsEditable ;
729  else
730  return flags & ~(Qt::ItemIsEditable|Qt::ItemIsEnabled) ;
731  case UserName:
732  case Password:
733  if ( isReadOnlyRow( row ) )
734  return flags & ~(Qt::ItemIsEditable|Qt::ItemIsEnabled) ;
735  else
736  return flags | Qt::ItemIsEditable ;
737  case X509:
738  if ( !isLdapRow( row ) )
739  return flags & ~(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled) ;
740  // fall through
741  case OpenPGP:
742  if ( isReadOnlyRow( row ) )
743  return flags & ~(Qt::ItemIsUserCheckable|Qt::ItemIsEnabled) ;
744  else
745  return flags | Qt::ItemIsUserCheckable ;
746  }
747  return flags;
748 }
749 
750 bool Model::setData( const QModelIndex & idx, const QVariant & value, int role ) {
751  const unsigned int row = idx.row();
752  if ( !idx.isValid() || row >= m_items.size() )
753  return false;
754  if ( isReadOnlyRow( row ) )
755  return false;
756  if ( !doSetData( row, idx.column(), value, role ) )
757  return false;
758  emit dataChanged( idx, idx );
759  return true;
760 }
761 
762 bool Model::doSetData( unsigned int row, unsigned int column, const QVariant & value, int role ) {
763  if ( role == Qt::EditRole )
764  switch ( column ) {
765  case Scheme:
766  if ( is_default_port( m_items[row].url ) ) {
767  // drag the port along with scheme changes
768  m_items[row].url.setPort( -1 );
769  const QModelIndex changed = index( row, Port );
770  emit dataChanged( changed, changed );
771  }
772  m_items[row].url.setProtocol( value.toString() );
773  return true;
774  case Host:
775  if ( display_host( m_items[row].url ) != m_items[row].url.host() ) {
776  m_items[row].url.setProtocol( display_scheme( m_items[row].url ) );
777  m_items[row].url.setPath( QLatin1String("/") );
778  }
779  m_items[row].url.setHost( value.toString() );
780  return true;
781  case Port:
782  if ( value.toUInt() == default_port( display_scheme( m_items[row].url ) ) )
783  m_items[row].url.setPort( -1 );
784  else
785  m_items[row].url.setPort( value.toUInt() );
786  return true;
787  case BaseDN:
788  if ( value.toString().isEmpty() ) {
789  m_items[row].url.setPath( QString() );
790  m_items[row].url.setQuery( QString() );
791  } else {
792  m_items[row].url.setPath( QLatin1String("/") ); // workaround KUrl parsing bug
793  m_items[row].url.setQuery( value.toString() );
794  }
795  return true;
796  case UserName:
797  m_items[row].url.setUserName( value.toString() );
798  return true;
799  case Password:
800  m_items[row].url.setPassword( value.toString() );
801  return true;
802  }
803  if ( role == Qt::CheckStateRole )
804  switch ( column ) {
805  case X509:
806  m_items[row].x509 = value.toInt() == Qt::Checked ;
807  return true;
808  case OpenPGP:
809  {
810  const bool on = value.toInt() == Qt::Checked ;
811  if ( on )
812  setExclusivePgpFlag( row );
813  else
814  m_items[row].pgp = false;
815  }
816  return true;
817  }
818  return false;
819 }
820 
821 void Model::setExclusivePgpFlag( unsigned int row ) {
822  if ( row >= m_items.size() || m_items[row].pgp )
823  return;
824  m_items[row].pgp = true; // dataChanged() for this one is supposed to be emitted by the caller
825  for ( unsigned int i = 0, end = m_items.size() ; i < end ; ++i )
826  if ( i != row )
827  if ( m_items[i].pgp ) {
828  m_items[i].pgp = false;
829  const QModelIndex changed = index( i, OpenPGP );
830  emit dataChanged( changed, changed );
831  break;
832  }
833 }
834 
835 // static
836 QString Model::toolTipForColumn( int column ) {
837  switch ( column ) {
838  case Scheme: return i18n("Select the access protocol (scheme) that the "
839  "directory service is available through.");
840  case Host: return i18n("Enter the name or IP address of the server "
841  "hosting the directory service.");
842  case Port: return i18n("<b>(Optional, the default is fine in most cases)</b> "
843  "Pick the port number the directory service is "
844  "listening on.");
845  case BaseDN: return i18n("<b>(Only for LDAP)</b> "
846  "Enter the base DN for this LDAP server to "
847  "limit searches to only that subtree of the directory.");
848  case UserName: return i18n("<b>(Optional)</b> "
849  "Enter your user name here, if needed.");
850  case Password: return i18n("<b>(Optional, not recommended)</b> "
851  "Enter your password here, if needed. "
852  "Note that the password will be saved in the clear "
853  "in a config file in your home directory.");
854  case X509: return i18n("Check this column if this directory service is "
855  "providing S/MIME (X.509) certificates.");
856  case OpenPGP: return i18n("Check this column if this directory service is "
857  "providing OpenPGP certificates.");
858  default:
859  return QString();
860  }
861 }
862 
863 #include "directoryserviceswidget.moc"
864 #include "moc_directoryserviceswidget.cpp"
Kleo::DirectoryServicesWidget::clear
void clear()
Definition: directoryserviceswidget.cpp:601
Kleo::DirectoryServicesWidget::DirectoryServicesWidget
DirectoryServicesWidget(QWidget *parent=0, Qt::WindowFlags f=0)
Definition: directoryserviceswidget.cpp:530
Kleo::DirectoryServicesWidget::openPGPServices
KUrl::List openPGPServices() const
Definition: directoryserviceswidget.cpp:580
Kleo::DirectoryServicesWidget::Scheme
Scheme
Definition: directoryserviceswidget.h:48
QWidget
QString
Kleo::DirectoryServicesWidget::~DirectoryServicesWidget
~DirectoryServicesWidget()
Definition: directoryserviceswidget.cpp:537
QObject
label
const char * label
Definition: cryptoconfigmodule.cpp:516
Kleo::DirectoryServicesWidget::HTTP
Definition: directoryserviceswidget.h:51
Kleo::DirectoryServicesWidget::addX509Services
void addX509Services(const KUrl::List &urls)
Definition: directoryserviceswidget.cpp:588
Kleo::DirectoryServicesWidget::changed
void changed()
Kleo::DirectoryServicesWidget::x509Services
KUrl::List x509Services() const
Definition: directoryserviceswidget.cpp:593
Kleo::DirectoryServicesWidget::FTP
Definition: directoryserviceswidget.h:52
Kleo::DirectoryServicesWidget::addOpenPGPServices
void addOpenPGPServices(const KUrl::List &urls)
Definition: directoryserviceswidget.cpp:575
Kleo::DirectoryServicesWidget::HKP
Definition: directoryserviceswidget.h:50
Kleo::DirectoryServicesWidget::setReadOnlyProtocols
void setReadOnlyProtocols(Protocols protocols)
Definition: directoryserviceswidget.cpp:562
Kleo::DirectoryServicesWidget::LDAP
Definition: directoryserviceswidget.h:53
Kleo::DirectoryServicesWidget::setAllowedSchemes
void setAllowedSchemes(Schemes schemes)
Definition: directoryserviceswidget.cpp:541
Kleo::DirectoryServicesWidget
Definition: directoryserviceswidget.h:42
kdtools::find_if
boost::range_iterator< C >::type find_if(C &c, P p)
Definition: stl_util.h:336
Kleo::DirectoryServicesWidget::allowedProtocols
Protocols allowedProtocols() const
Definition: directoryserviceswidget.cpp:558
Kleo::DirectoryServicesWidget::allowedSchemes
Schemes allowedSchemes() const
Definition: directoryserviceswidget.cpp:546
Kleo::DirectoryServicesWidget::readOnlyProtocols
Protocols readOnlyProtocols() const
Definition: directoryserviceswidget.cpp:571
directoryserviceswidget.h
Kleo::DirectoryServicesWidget::setAllowedProtocols
void setAllowedProtocols(Protocols protocols)
Definition: directoryserviceswidget.cpp:550
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:57:48 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libkleo

Skip menu "libkleo"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal