33 #include <config-kleopatra.h>
37 #ifndef QT_NO_DIRMODEL
40 #include <KLocalizedString>
41 #include <KMessageBox>
43 #include <QHBoxLayout>
45 #include <QStringList>
46 #include <QVBoxLayout>
49 #include <QSortFilterProxyModel>
51 #include <QProgressBar>
52 #include <QDialogButtonBox>
53 #include <QPushButton>
54 #include <QHeaderView>
56 #include <boost/static_assert.hpp>
61 using namespace Kleo::Crypto;
62 using namespace Kleo::Crypto::Gui;
63 using namespace boost;
67 static Qt::GlobalColor statusColor[] = {
75 class ColorizedFileSystemModel :
public QDirModel {
78 explicit ColorizedFileSystemModel( QObject * parent=0 )
79 : QDirModel( parent ),
85 QVariant data(
const QModelIndex & mi,
int role=Qt::DisplayRole )
const {
86 if ( mi.isValid() && role == Qt::BackgroundRole ) {
87 const QHash<QString,VerifyChecksumsDialog::Status>::const_iterator
88 it = statusMap.find( filePath( mi ) );
89 if ( it != statusMap.end() )
90 if (
const Qt::GlobalColor c = statusColor[*it] )
93 return QDirModel::data( mi, role );
103 const QModelIndex mi = index( file );
104 const QString canonical = filePath( mi );
105 if ( canonical.isEmpty() ) {
106 kDebug() <<
"can't locate file " << file;
110 const QHash<QString,VerifyChecksumsDialog::Status>::iterator
111 it = statusMap.find( canonical );
113 if ( it != statusMap.end() )
119 statusMap[canonical] =
status;
121 emitDataChangedFor( mi );
124 void clearStatusInformation() {
127 QHash<QString,VerifyChecksumsDialog::Status> oldStatusMap;
128 swap( statusMap, oldStatusMap );
130 for ( QHash<QString,VerifyChecksumsDialog::Status>::const_iterator it = oldStatusMap.constBegin(), end = oldStatusMap.constEnd() ; it != end ; ++it )
131 emitDataChangedFor( it.key() );
135 void emitDataChangedFor(
const QString & file ) {
136 emitDataChangedFor( index( file ) );
138 void emitDataChangedFor(
const QModelIndex & mi ) {
139 const QModelIndex p = parent( mi );
140 emit dataChanged( index( mi.row(), 0, p ), index( mi.row(), columnCount( p ) - 1, p ) );
144 QHash<QString,VerifyChecksumsDialog::Status> statusMap;
148 static int find_layout_item(
const QBoxLayout & blay ) {
149 for (
int i = 0, end = blay.count() ; i < end ; ++i )
150 if ( QLayoutItem * item = blay.itemAt( i ) )
151 if ( item->layout() )
161 BaseWidget( QDirModel * model,
QWidget * parent, QVBoxLayout * vlay )
170 const int row = find_layout_item( *vlay );
171 vlay->insertWidget( row, &label );
172 vlay->insertWidget( row+1, &view, 1 );
174 proxy.setSourceModel( model );
176 view.setModel( &proxy );
179 for(
int i = 0; i < proxy.columnCount(); ++i )
180 view.resizeColumnToContents( i );
183 view.header()->resizeSection( 0, qMax( view.header()->sectionSize( 0 ), 220 ) );
184 view.header()->resizeSection( 1, qMax( view.header()->sectionSize( 1 ), 75 ) );
185 view.header()->resizeSection( 2, qMax( view.header()->sectionSize( 2 ), 75 ) );
186 view.header()->resizeSection( 3, qMax( view.header()->sectionSize( 3 ), 140 ) );
188 for(
int i = 0; i < proxy.rowCount(); ++i )
189 r = r.united( view.visualRect( proxy.index( proxy.columnCount() - 1, i ) ) );
190 view.setMinimumSize( QSize( qBound( r.width() + 4 * view.frameWidth(), 220+75+75+140 + 4 * view.frameWidth(), 1024 ),
191 qBound( r.height(), 220, 512 ) ) );
194 void setBase(
const QString & base ) {
195 label.setText( base );
196 if ( QDirModel * fsm = qobject_cast<QDirModel*>( proxy.sourceModel() ) ) {
197 view.setRootIndex( proxy.mapFromSource( fsm->index( base ) ) );
199 kWarning() <<
"expect a QDirModel-derived class as proxy.sourceModel(), got ";
200 if ( !proxy.sourceModel() ) {
201 kWarning() <<
"a null pointer";
203 kWarning() << proxy.sourceModel()->metaObject()->className();
212 class VerifyChecksumsDialog::Private {
213 friend class ::Kleo::Crypto::Gui::VerifyChecksumsDialog;
223 qRegisterMetaType<Status>(
"Kleo::Crypto::Gui::VerifyChecksumsDialog::Status" );
227 void slotErrorButtonClicked() {
228 KMessageBox::errorList(
q, i18n(
"The following errors and warnings were recorded:"),
229 errors, i18n(
"Checksum Verification Errors") );
233 void updateErrors() {
234 const bool active = ui.isProgressBarActive();
235 ui.progressLabel.setVisible( active );
236 ui.progressBar. setVisible( active );
237 ui.errorLabel. setVisible( !active );
238 ui.errorButton. setVisible( !active && !errors.empty() );
239 if ( errors.empty() )
240 ui.errorLabel.setText( i18n(
"No errors occurred" ) );
242 ui.errorLabel.setText( i18np(
"One error occurred",
"%1 errors occurred", errors.size() ) );
248 ColorizedFileSystemModel model;
251 std::vector<BaseWidget*> baseWidgets;
252 QLabel progressLabel;
253 QProgressBar progressBar;
255 QPushButton errorButton;
256 QDialogButtonBox buttonBox;
262 progressLabel( i18n(
"Progress:"), q ),
264 errorLabel( i18n(
"No errors occurred"), q ),
265 errorButton( i18nc(
"Show Errors",
"Show"), q ),
266 buttonBox( QDialogButtonBox::Close, Qt::Horizontal, q ),
278 errorButton.setAutoDefault(
false );
280 hlay[0].addWidget( &progressLabel );
281 hlay[0].addWidget( &progressBar, 1 );
283 hlay[1].addWidget( &errorLabel, 1 );
284 hlay[1].addWidget( &errorButton );
286 vlay.addLayout( &hlay[0] );
287 vlay.addLayout( &hlay[1] );
288 vlay.addWidget( &buttonBox );
293 QPushButton * close = closeButton();
295 connect( close, SIGNAL(clicked()), q, SIGNAL(canceled()) );
296 connect( close, SIGNAL(clicked()), q, SLOT(accept()) );
298 connect( &errorButton, SIGNAL(clicked()), q, SLOT(slotErrorButtonClicked()) );
302 qDeleteAll( baseWidgets );
305 QPushButton * closeButton()
const {
306 return buttonBox.button( QDialogButtonBox::Close );
309 void setBases(
const QStringList & bases, QDirModel * model ) {
312 for (
unsigned int i = baseWidgets.size(), end = bases.size() ; i < end ; ++i )
313 baseWidgets.push_back(
new BaseWidget( model, vlay.parentWidget(), &vlay ) );
316 for (
unsigned int i = bases.size(), end = baseWidgets.size() ; i < end ; ++i ) {
317 delete baseWidgets.back();
318 baseWidgets.pop_back();
321 assert( static_cast<unsigned>( bases.size() ) == baseWidgets.size() );
324 for (
unsigned int i = 0 ; i < baseWidgets.size() ; ++i )
325 baseWidgets[i]->setBase( bases[i] );
329 void setProgress(
int cur,
int tot ) {
330 progressBar.setMaximum( tot );
331 progressBar.setValue( cur );
334 bool isProgressBarActive()
const {
335 const int tot = progressBar.maximum();
336 const int cur = progressBar.value();
337 return !tot || cur != tot ;
345 d( new Private( this ) )
354 if ( d->bases == bases )
357 d->ui.setBases( bases, &d->model );
362 if ( d->errors == errors )
370 d->ui.setProgress( cur, tot );
376 d->model.setStatus( file, status );
383 d->model.clearStatusInformation();
386 #include "verifychecksumsdialog.moc"
387 #include "moc_verifychecksumsdialog.cpp"
389 #endif // QT_NO_DIRMODEL
VerifyChecksumsDialog(QWidget *parent=0, Qt::WindowFlags flags=0)
static const char * flags[]
void setErrors(const QStringList &errors)
void setStatus(const QString &file, Kleo::Crypto::Gui::VerifyChecksumsDialog::Status status)
void setProgress(int current, int total)
VerifyChecksumsDialog::Status status
void clearStatusInformation()
BOOST_STATIC_ASSERT((sizeof icons/sizeof(*icons)==NumStates))
void setBaseDirectories(const QStringList &bases)