1 //////////////////////////////////////////////////////////////////////////////
2 // breezeexceptionlistwidget.cpp
3 // -------------------
4 //
5 // SPDX-FileCopyrightText: 2009 Hugo Pereira Da Costa <hugo.pereira@free.fr>
6 //
7 // SPDX-License-Identifier: MIT
8 //////////////////////////////////////////////////////////////////////////////
9 
10 #include "breezeexceptionlistwidget.h"
11 #include "breezeexceptiondialog.h"
12 
13 #include <KLocalizedString>
14 
15 #include <QMessageBox>
16 #include <QPointer>
17 #include <QIcon>
18 
19 //__________________________________________________________
20 namespace Breeze
21 {
22 
23     //__________________________________________________________
ExceptionListWidget(QWidget * parent)24     ExceptionListWidget::ExceptionListWidget( QWidget* parent ):
25         QWidget( parent )
26     {
27 
28         // ui
29         m_ui.setupUi( this );
30 
31         // list
32         m_ui.exceptionListView->setAllColumnsShowFocus( true );
33         m_ui.exceptionListView->setRootIsDecorated( false );
34         m_ui.exceptionListView->setSortingEnabled( false );
35         m_ui.exceptionListView->setModel( &model() );
36         m_ui.exceptionListView->sortByColumn( ExceptionModel::ColumnType, Qt::AscendingOrder );
37         m_ui.exceptionListView->setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::Ignored ) );
38 
39         m_ui.moveUpButton->setIcon( QIcon::fromTheme( QStringLiteral( "arrow-up" ) ) );
40         m_ui.moveDownButton->setIcon( QIcon::fromTheme( QStringLiteral( "arrow-down" ) ) );
41         m_ui.addButton->setIcon( QIcon::fromTheme( QStringLiteral( "list-add" ) ) );
42         m_ui.removeButton->setIcon( QIcon::fromTheme( QStringLiteral( "list-remove" ) ) );
43         m_ui.editButton->setIcon( QIcon::fromTheme( QStringLiteral( "edit-rename" ) ) );
44 
45         connect( m_ui.addButton, &QAbstractButton::clicked, this, &ExceptionListWidget::add );
46         connect( m_ui.editButton, &QAbstractButton::clicked, this, &ExceptionListWidget::edit );
47         connect( m_ui.removeButton, &QAbstractButton::clicked, this, &ExceptionListWidget::remove );
48         connect( m_ui.moveUpButton, &QAbstractButton::clicked, this, &ExceptionListWidget::up );
49         connect( m_ui.moveDownButton, &QAbstractButton::clicked, this, &ExceptionListWidget::down );
50 
51         connect( m_ui.exceptionListView, &QAbstractItemView::activated, this, &ExceptionListWidget::edit );
52         connect( m_ui.exceptionListView, &QAbstractItemView::clicked, this, &ExceptionListWidget::toggle );
53         connect( m_ui.exceptionListView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &ExceptionListWidget::updateButtons );
54 
55         updateButtons();
56         resizeColumns();
57 
58 
59     }
60 
61     //__________________________________________________________
setExceptions(const InternalSettingsList & exceptions)62     void ExceptionListWidget::setExceptions( const InternalSettingsList& exceptions )
63     {
64         model().set( exceptions );
65         resizeColumns();
66         setChanged( false );
67     }
68 
69     //__________________________________________________________
exceptions()70     InternalSettingsList ExceptionListWidget::exceptions()
71     {
72         return model().get();
73         setChanged( false );
74     }
75 
76     //__________________________________________________________
updateButtons()77     void ExceptionListWidget::updateButtons()
78     {
79 
80         bool hasSelection( !m_ui.exceptionListView->selectionModel()->selectedRows().empty() );
81         m_ui.removeButton->setEnabled( hasSelection );
82         m_ui.editButton->setEnabled( hasSelection );
83 
84         m_ui.moveUpButton->setEnabled( hasSelection && !m_ui.exceptionListView->selectionModel()->isRowSelected( 0, QModelIndex() ) );
85         m_ui.moveDownButton->setEnabled( hasSelection && !m_ui.exceptionListView->selectionModel()->isRowSelected( model().rowCount()-1, QModelIndex() ) );
86 
87     }
88 
89 
90     //_______________________________________________________
add()91     void ExceptionListWidget::add()
92     {
93 
94 
95         QPointer<ExceptionDialog> dialog = new ExceptionDialog( this );
96         dialog->setWindowTitle( i18n( "New Exception - Breeze Settings" ) );
97         InternalSettingsPtr exception( new InternalSettings() );
98 
99         exception->load();
100 
101         dialog->setException( exception );
102 
103         // run dialog and check existence
104         if( !dialog->exec() )
105         {
106             delete dialog;
107             return;
108         }
109 
110         dialog->save();
111         delete dialog;
112 
113         // check exceptions
114         if( !checkException( exception ) ) return;
115 
116         // create new item
117         model().add( exception );
118         setChanged( true );
119 
120         // make sure item is selected
121         QModelIndex index( model().index( exception ) );
122         if( index != m_ui.exceptionListView->selectionModel()->currentIndex() )
123         {
124             m_ui.exceptionListView->selectionModel()->select( index,  QItemSelectionModel::Clear|QItemSelectionModel::Select|QItemSelectionModel::Rows );
125             m_ui.exceptionListView->selectionModel()->setCurrentIndex( index,  QItemSelectionModel::Current|QItemSelectionModel::Rows );
126         }
127 
128         resizeColumns();
129 
130     }
131 
132     //_______________________________________________________
edit()133     void ExceptionListWidget::edit()
134     {
135 
136         // retrieve selection
137         QModelIndex current( m_ui.exceptionListView->selectionModel()->currentIndex() );
138         if( ! model().contains( current ) ) return;
139 
140         InternalSettingsPtr exception( model().get( current ) );
141 
142         // create dialog
143         QPointer<ExceptionDialog> dialog( new ExceptionDialog( this ) );
144         dialog->setWindowTitle( i18n( "Edit Exception - Breeze Settings" ) );
145         dialog->setException( exception );
146 
147         // map dialog
148         if( !dialog->exec() )
149         {
150             delete dialog;
151             return;
152         }
153 
154         // check modifications
155         if( !dialog->isChanged() ) return;
156 
157         // retrieve exception
158         dialog->save();
159         delete dialog;
160 
161         // check new exception validity
162         checkException( exception );
163         resizeColumns();
164 
165         setChanged( true );
166 
167     }
168 
169     //_______________________________________________________
remove()170     void ExceptionListWidget::remove()
171     {
172 
173         // confirmation dialog
174         {
175             QMessageBox messageBox( QMessageBox::Question, i18n("Question - Breeze Settings" ), i18n("Remove selected exception?"), QMessageBox::Yes | QMessageBox::Cancel );
176             messageBox.button( QMessageBox::Yes )->setText( i18n("Remove") );
177             messageBox.setDefaultButton( QMessageBox::Cancel );
178             if( messageBox.exec() == QMessageBox::Cancel ) return;
179         }
180 
181         // remove
182         model().remove( model().get( m_ui.exceptionListView->selectionModel()->selectedRows() ) );
183         resizeColumns();
184         updateButtons();
185 
186         setChanged( true );
187 
188     }
189 
190     //_______________________________________________________
toggle(const QModelIndex & index)191     void ExceptionListWidget::toggle( const QModelIndex& index )
192     {
193 
194         if( !model().contains( index ) ) return;
195         if( index.column() != ExceptionModel::ColumnEnabled ) return;
196 
197         // get matching exception
198         InternalSettingsPtr exception( model().get( index ) );
199         exception->setEnabled( !exception->enabled() );
200         setChanged( true );
201 
202     }
203 
204     //_______________________________________________________
up()205     void ExceptionListWidget::up()
206     {
207 
208         InternalSettingsList selection( model().get( m_ui.exceptionListView->selectionModel()->selectedRows() ) );
209         if( selection.empty() ) { return; }
210 
211         // retrieve selected indexes in list and store in model
212         QModelIndexList selectedIndices( m_ui.exceptionListView->selectionModel()->selectedRows() );
213         InternalSettingsList selectedExceptions( model().get( selectedIndices ) );
214 
215         InternalSettingsList currentException( model().get() );
216         InternalSettingsList newExceptions;
217 
218         for( InternalSettingsList::const_iterator iter = currentException.constBegin(); iter != currentException.constEnd(); ++iter )
219         {
220 
221             // check if new list is not empty, current index is selected and last index is not.
222             // if yes, move.
223             if(
224                 !( newExceptions.empty() ||
225                 selectedIndices.indexOf( model().index( *iter ) ) == -1 ||
226                 selectedIndices.indexOf( model().index( newExceptions.back() ) ) != -1
227                 ) )
228             {
229                 InternalSettingsPtr last( newExceptions.back() );
230                 newExceptions.removeLast();
231                 newExceptions.append( *iter );
232                 newExceptions.append( last );
233             } else newExceptions.append( *iter );
234 
235         }
236 
237         model().set( newExceptions );
238 
239         // restore selection
240         m_ui.exceptionListView->selectionModel()->select( model().index( selectedExceptions.front() ),  QItemSelectionModel::Clear|QItemSelectionModel::Select|QItemSelectionModel::Rows );
241         for( InternalSettingsList::const_iterator iter = selectedExceptions.constBegin(); iter != selectedExceptions.constEnd(); ++iter )
242         { m_ui.exceptionListView->selectionModel()->select( model().index( *iter ), QItemSelectionModel::Select|QItemSelectionModel::Rows ); }
243 
244         setChanged( true );
245 
246     }
247 
248     //_______________________________________________________
down()249     void ExceptionListWidget::down()
250     {
251 
252         InternalSettingsList selection( model().get( m_ui.exceptionListView->selectionModel()->selectedRows() ) );
253         if( selection.empty() )
254         { return; }
255 
256         // retrieve selected indexes in list and store in model
257         QModelIndexList selectedIndices( m_ui.exceptionListView->selectionModel()->selectedIndexes() );
258         InternalSettingsList selectedExceptions( model().get( selectedIndices ) );
259 
260         InternalSettingsList currentExceptions( model().get() );
261         InternalSettingsList newExceptions;
262 
263         InternalSettingsListIterator iter( currentExceptions );
264         iter.toBack();
265         while( iter.hasPrevious() )
266         {
267 
268             InternalSettingsPtr current( iter.previous() );
269 
270             // check if new list is not empty, current index is selected and last index is not.
271             // if yes, move.
272             if(
273                 !( newExceptions.empty() ||
274                 selectedIndices.indexOf( model().index( current ) ) == -1 ||
275                 selectedIndices.indexOf( model().index( newExceptions.front() ) ) != -1
276                 ) )
277             {
278 
279                 InternalSettingsPtr first( newExceptions.front() );
280                 newExceptions.removeFirst();
281                 newExceptions.prepend( current );
282                 newExceptions.prepend( first );
283 
284             } else newExceptions.prepend( current );
285         }
286 
287         model().set( newExceptions );
288 
289         // restore selection
290         m_ui.exceptionListView->selectionModel()->select( model().index( selectedExceptions.front() ),  QItemSelectionModel::Clear|QItemSelectionModel::Select|QItemSelectionModel::Rows );
291         for( InternalSettingsList::const_iterator iter = selectedExceptions.constBegin(); iter != selectedExceptions.constEnd(); ++iter )
292         { m_ui.exceptionListView->selectionModel()->select( model().index( *iter ), QItemSelectionModel::Select|QItemSelectionModel::Rows ); }
293 
294         setChanged( true );
295 
296     }
297 
298     //_______________________________________________________
resizeColumns() const299     void ExceptionListWidget::resizeColumns() const
300     {
301         m_ui.exceptionListView->resizeColumnToContents( ExceptionModel::ColumnEnabled );
302         m_ui.exceptionListView->resizeColumnToContents( ExceptionModel::ColumnType );
303         m_ui.exceptionListView->resizeColumnToContents( ExceptionModel::ColumnRegExp );
304     }
305 
306     //_______________________________________________________
checkException(InternalSettingsPtr exception)307     bool ExceptionListWidget::checkException( InternalSettingsPtr exception )
308     {
309 
310         while( exception->exceptionPattern().isEmpty() || !QRegExp( exception->exceptionPattern() ).isValid() )
311         {
312 
313             QMessageBox::warning( this, i18n( "Warning - Breeze Settings" ), i18n("Regular Expression syntax is incorrect") );
314             QPointer<ExceptionDialog> dialog( new ExceptionDialog( this ) );
315             dialog->setException( exception );
316             if( dialog->exec() == QDialog::Rejected )
317             {
318                 delete dialog;
319                 return false;
320             }
321 
322             dialog->save();
323             delete dialog;
324         }
325 
326         return true;
327     }
328 
329 }
330