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

libkleo

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

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