33 #include <config-kleopatra.h>
43 #include <kleo/stl_util.h>
44 #include <kleo/keyfilter.h>
45 #include <kleo/keyfiltermanager.h>
47 #include <gpgme++/key.h>
49 #include <KLocalizedString>
51 #include <KConfigGroup>
54 #include <KActionCollection>
55 #include <KInputDialog>
58 #include <QToolButton>
61 #include <QVBoxLayout>
68 using namespace boost;
69 using namespace GpgME;
78 Page(
const KConfigGroup & group,
QWidget * parent=0 );
81 void setTemporary(
bool temporary );
82 bool isTemporary()
const {
return m_isTemporary; }
84 void setHierarchicalView(
bool hierarchical );
85 void setStringFilter(
const QString & filter );
88 QString title()
const {
return m_title.
isEmpty() && keyFilter() ? keyFilter()->name() : m_title ; }
89 void setTitle(
const QString & title );
92 void setToolTip(
const QString & tip );
94 bool canBeClosed()
const {
return m_canBeClosed; }
95 bool canBeRenamed()
const {
return m_canBeRenamed; }
96 bool canChangeStringFilter()
const {
return m_canChangeStringFilter; }
97 bool canChangeKeyFilter()
const {
return m_canChangeKeyFilter && !m_isTemporary; }
98 bool canChangeHierarchical()
const {
return m_canChangeHierarchical; }
100 void saveTo( KConfigGroup & group )
const;
102 Page * clone()
const {
return new Page( *
this ); }
104 void liftAllRestrictions() {
105 m_canBeClosed = m_canBeRenamed = m_canChangeStringFilter = m_canChangeKeyFilter = m_canChangeHierarchical =
true;
109 void titleChanged(
const QString & title );
117 bool m_isTemporary : 1;
118 bool m_canBeClosed : 1;
119 bool m_canBeRenamed : 1;
120 bool m_canChangeStringFilter : 1;
121 bool m_canChangeKeyFilter : 1;
122 bool m_canChangeHierarchical : 1;
128 m_title( other.m_title ),
129 m_toolTip( other.m_toolTip ),
130 m_isTemporary( other.m_isTemporary ),
131 m_canBeClosed( other.m_canBeClosed ),
132 m_canBeRenamed( other.m_canBeRenamed ),
133 m_canChangeStringFilter( other.m_canChangeStringFilter ),
134 m_canChangeKeyFilter( other.m_canChangeKeyFilter ),
135 m_canChangeHierarchical( other.m_canChangeHierarchical )
141 :
KeyTreeView( text, KeyFilterManager::instance()->keyFilterByID( id ), proxy, parent ),
143 m_toolTip( toolTip ),
144 m_isTemporary( false ),
145 m_canBeClosed( true ),
146 m_canBeRenamed( true ),
147 m_canChangeStringFilter( true ),
148 m_canChangeKeyFilter( true ),
149 m_canChangeHierarchical( true )
164 KeyFilterManager::instance()->keyFilterByID( group.readEntry(
KEY_FILTER_ENTRY ) ),
168 m_isTemporary( false ),
169 m_canBeClosed( !group.isImmutable() ),
170 m_canBeRenamed( !group.isEntryImmutable(
TITLE_ENTRY ) ),
179 group.readEntry(
SORT_DESCENDING,
true ) ? Qt::DescendingOrder : Qt::AscendingOrder );
188 void Page::saveTo( KConfigGroup & group )
const {
196 group.writeEntry(
SORT_DESCENDING, sortOrder() == Qt::DescendingOrder );
199 void Page::setStringFilter(
const QString & filter ) {
200 if ( !m_canChangeStringFilter )
202 KeyTreeView::setStringFilter( filter );
206 if ( !canChangeKeyFilter() )
208 const QString oldTitle = title();
209 KeyTreeView::setKeyFilter( filter );
210 const QString newTitle = title();
211 if ( oldTitle != newTitle )
212 emit titleChanged( newTitle );
215 void Page::setTitle(
const QString & t ) {
218 if ( !m_canBeRenamed )
220 const QString oldTitle = title();
222 const QString newTitle = title();
223 if ( oldTitle != newTitle )
224 emit titleChanged( newTitle );
227 void Page::setToolTip(
const QString & tip ) {
228 if ( tip == m_toolTip )
230 if ( !m_canBeRenamed )
235 if ( oldTip != newTip )
236 emit titleChanged( title() );
239 void Page::setHierarchicalView(
bool on ) {
240 if ( !m_canChangeHierarchical )
242 KeyTreeView::setHierarchicalView( on );
245 void Page::setTemporary(
bool on ) {
246 if ( on == m_isTemporary )
259 class TabWidget::Private {
260 friend class ::Kleo::TabWidget;
267 void slotContextMenu(
const QPoint & p ) {
268 slotContextMenu( 0, p );
271 void currentIndexChanged(
int index );
272 void slotPageTitleChanged(
const QString & title );
274 void slotPageStringFilterChanged(
const QString & filter );
275 void slotPageHierarchyChanged(
bool on );
277 #ifndef QT_NO_INPUTDIALOG
278 void slotRenameCurrentTab() {
279 renamePage( currentPage() );
281 #endif // QT_NO_INPUTDIALOG
283 void slotDuplicateCurrentTab() {
284 duplicatePage( currentPage() );
286 void slotCloseCurrentTab() {
287 closePage( currentPage() );
289 void slotMoveCurrentTabLeft() {
290 movePageLeft( currentPage() );
292 void slotMoveCurrentTabRight() {
293 movePageRight( currentPage() );
295 void slotToggleHierarchicalView(
bool on ) {
296 toggleHierarchicalView( currentPage(), on );
298 void slotExpandAll() {
299 expandAll( currentPage() );
301 void slotCollapseAll() {
302 collapseAll( currentPage() );
305 #ifndef QT_NO_INPUTDIALOG
306 void renamePage(
Page * page );
308 void duplicatePage(
Page * page );
309 void closePage(
Page * page );
310 void movePageLeft(
Page * page );
311 void movePageRight(
Page * page );
312 void toggleHierarchicalView(
Page * page,
bool on );
313 void expandAll(
Page * page );
314 void collapseAll(
Page * page );
316 void enableDisableCurrentPageActions();
317 void enableDisablePageActions(
QAction * actions[],
const Page * page );
319 Page * currentPage()
const {
320 assert( !tabWidget.currentWidget() || qobject_cast<
Page*>( tabWidget.currentWidget() ) );
321 return static_cast<Page*
>( tabWidget.currentWidget() );
323 Page * page(
unsigned int idx )
const {
324 assert( !tabWidget.widget( idx ) || qobject_cast<
Page*>( tabWidget.widget( idx ) ) );
325 return static_cast<Page*
>( tabWidget.widget( idx ) );
328 Page * senderPage()
const {
329 QObject *
const sender =
q->sender();
330 assert( !sender || qobject_cast<Page*>( sender ) );
331 return static_cast<Page*
>( sender );
334 bool isSenderCurrentPage()
const {
335 Page *
const sp = senderPage();
336 return sp && sp == currentPage();
340 void setCornerAction(
QAction * action, Qt::Corner corner );
345 KTabWidget tabWidget;
360 QAction * currentPageActions[NumPageActions];
361 QAction * otherPageActions[NumPageActions];
364 TabWidget::Private::Private(
TabWidget * qq )
367 hierarchicalModel( 0 ),
374 layout.setMargin( 0 );
375 layout.addWidget( &tabWidget );
377 tabWidget.setTabBarHidden(
true );
378 tabWidget.setMovable(
true );
380 connect( &tabWidget, SIGNAL(currentChanged(
int)),
381 q, SLOT(currentIndexChanged(
int)) );
382 connect( &tabWidget, SIGNAL(contextMenu(
QPoint)),
383 q, SLOT(slotContextMenu(
QPoint)) );
388 "window_new_tab", i18n(
"New Tab"), i18n(
"Open a new tab"),
389 "tab-new-background",
q, SLOT(slotNewTab()),
QLatin1String(
"CTRL+SHIFT+N"),
false,
true
395 {
"window_rename_tab", i18n(
"Rename Tab..."), i18n(
"Rename this tab"),
396 "edit-rename",
q, SLOT(slotRenameCurrentTab()),
QLatin1String(
"CTRL+SHIFT+R"),
false,
false },
397 {
"window_duplicate_tab", i18n(
"Duplicate Tab"), i18n(
"Duplicate this tab"),
398 "tab-duplicate",
q, SLOT(slotDuplicateCurrentTab()),
QLatin1String(
"CTRL+SHIFT+D"),
false,
true },
399 {
"window_close_tab", i18n(
"Close Tab"), i18n(
"Close this tab"),
400 "tab-close",
q, SLOT(slotCloseCurrentTab()),
QLatin1String(
"CTRL+SHIFT+W"),
false,
false },
401 {
"window_move_tab_left", i18n(
"Move Tab Left"),
QString(),
402 0,
q, SLOT(slotMoveCurrentTabLeft()),
QLatin1String(
"CTRL+SHIFT+LEFT"),
false,
false },
403 {
"window_move_tab_right", i18n(
"Move Tab Right"),
QString(),
404 0,
q, SLOT(slotMoveCurrentTabRight()),
QLatin1String(
"CTRL+SHIFT+RIGHT"),
false,
false },
405 {
"window_view_hierarchical", i18n(
"Hierarchical Certificate List"),
QString(),
406 0,
q, SLOT(slotToggleHierarchicalView(
bool)),
QString(),
true,
false },
407 {
"window_expand_all", i18n(
"Expand All"),
QString(),
408 0,
q, SLOT(slotExpandAll()),
QLatin1String(
"CTRL+."),
false,
false },
409 {
"window_collapse_all", i18n(
"Collapse All"),
QString(),
410 0,
q, SLOT(slotCollapseAll()),
QLatin1String(
"CTRL+,"),
false,
false },
413 for (
unsigned int i = 0 ; i < NumPageActions ; ++i )
416 for (
unsigned int i = 0 ; i < NumPageActions ; ++i ) {
419 ad.
name = ad.
name + strlen(
"window_");
426 setCornerAction( newAction, Qt::TopLeftCorner );
427 setCornerAction( currentPageActions[Close], Qt::TopRightCorner );
430 void TabWidget::Private::slotContextMenu(
QWidget * w,
const QPoint & p ) {
431 assert( !w || qobject_cast<Page*>( w ) );
432 Page *
const contextMenuPage =
static_cast<Page*
>( w );
433 const Page *
const current = currentPage();
435 QAction **
const actions = contextMenuPage == current ? currentPageActions : otherPageActions ;
437 enableDisablePageActions( actions, contextMenuPage );
452 if ( contextMenuPage == current || action == newAction )
455 #ifndef QT_NO_INPUTDIALOG
456 if ( action == otherPageActions[Rename] )
457 renamePage( contextMenuPage );
458 #endif // QT_NO_INPUTDIALOG
459 else if ( action == otherPageActions[Duplicate] )
460 duplicatePage( contextMenuPage );
461 else if ( action == otherPageActions[Close] )
462 closePage( contextMenuPage );
463 else if ( action == otherPageActions[MoveLeft] )
464 movePageLeft( contextMenuPage );
465 else if ( action == otherPageActions[MoveRight] )
466 movePageRight( contextMenuPage );
470 void TabWidget::Private::currentIndexChanged(
int index ) {
471 const Page *
const page = this->page( index );
472 emit
q->currentViewChanged( page ? page->view() : 0 );
474 emit
q->stringFilterChanged( page ? page->stringFilter() :
QString() );
475 enableDisableCurrentPageActions();
478 void TabWidget::Private::enableDisableCurrentPageActions() {
479 const Page *
const page = currentPage();
481 emit
q->enableChangeStringFilter( page && page->canChangeStringFilter() );
482 emit
q->enableChangeKeyFilter( page && page->canChangeKeyFilter() );
484 enableDisablePageActions( currentPageActions, page );
487 void TabWidget::Private::enableDisablePageActions(
QAction * actions[],
const Page * p ) {
488 actions[Rename] ->
setEnabled( p && p->canBeRenamed() );
490 actions[Close] ->
setEnabled( p && p->canBeClosed() && tabWidget.count() > 1 );
491 actions[MoveLeft] ->
setEnabled( p && tabWidget.indexOf( const_cast<Page*>(p) ) != 0 );
492 actions[MoveRight] ->
setEnabled( p && tabWidget.indexOf( const_cast<Page*>(p) ) != tabWidget.count()-1 );
493 actions[Hierarchical]->
setEnabled( p && p->canChangeHierarchical() );
494 actions[Hierarchical]->
setChecked( p && p->isHierarchicalView() );
495 actions[ExpandAll] ->
setEnabled( p && p->isHierarchicalView() );
496 actions[CollapseAll] ->
setEnabled( p && p->isHierarchicalView() );
498 tabWidget.setTabBarHidden( tabWidget.count() < 2 );
501 void TabWidget::Private::slotPageTitleChanged(
const QString & ) {
502 if (
Page *
const page = senderPage() ) {
503 const int idx = tabWidget.indexOf( page );
504 tabWidget.setTabText( idx, page->title() );
505 tabWidget.setTabToolTip( idx, page->toolTip() );
510 if ( isSenderCurrentPage() )
511 emit
q->keyFilterChanged( kf );
514 void TabWidget::Private::slotPageStringFilterChanged(
const QString & filter ) {
515 if ( isSenderCurrentPage() )
516 emit
q->stringFilterChanged( filter );
519 void TabWidget::Private::slotPageHierarchyChanged(
bool ) {
520 enableDisableCurrentPageActions();
523 void TabWidget::Private::slotNewTab() {
525 addView( page, currentPage() );
526 tabWidget.setCurrentIndex( tabWidget.count()-1 );
529 void TabWidget::Private::renamePage(
Page * page ) {
533 const QString text = KInputDialog::getText( i18n(
"Rename Tab"), i18n(
"New tab title:"), page->title(), &ok,
q);
536 page->setTitle( text );
539 void TabWidget::Private::duplicatePage(
Page * page ) {
542 Page *
const clone = page->clone();
544 clone->liftAllRestrictions();
545 addView( clone, page );
548 void TabWidget::Private::closePage(
Page * page) {
549 if ( !page || !page->canBeClosed() || tabWidget.count() <= 1 )
551 emit
q->viewAboutToBeRemoved( page->view() );
552 tabWidget.removeTab( tabWidget.indexOf( page ) );
553 enableDisableCurrentPageActions();
556 void TabWidget::Private::movePageLeft(
Page * page ) {
559 const int idx = tabWidget.indexOf( page );
562 tabWidget.moveTab( idx, idx-1 );
563 enableDisableCurrentPageActions();
566 void TabWidget::Private::movePageRight(
Page * page ) {
569 const int idx = tabWidget.indexOf( page );
570 if ( idx < 0 || idx >= tabWidget.count()-1 )
572 tabWidget.moveTab( idx, idx+1 );
573 enableDisableCurrentPageActions();
576 void TabWidget::Private::toggleHierarchicalView(
Page * page,
bool on ) {
579 page->setHierarchicalView( on );
582 void TabWidget::Private::expandAll(
Page * page ) {
583 if ( !page || !page->view() )
585 page->view()->expandAll();
588 void TabWidget::Private::collapseAll(
Page * page ) {
589 if ( !page || !page->view() )
591 page->view()->collapseAll();
595 :
QWidget( p, f ),
d( new Private( this ) )
603 if ( model ==
d->flatModel )
605 d->flatModel = model;
606 for (
unsigned int i = 0, end =
count() ; i != end ; ++i )
607 if (
Page *
const page =
d->page( i ) )
608 page->setFlatModel( model );
616 if ( model ==
d->hierarchicalModel )
618 d->hierarchicalModel = model;
619 for (
unsigned int i = 0, end =
count() ; i != end ; ++i )
620 if (
Page *
const page =
d->page( i ) )
621 page->setHierarchicalModel( model );
625 return d->hierarchicalModel;
628 void TabWidget::Private::setCornerAction(
QAction * action, Qt::Corner corner ) {
633 tabWidget.setCornerWidget( b, corner );
637 if (
Page *
const page =
d->currentPage() )
638 page->setStringFilter( filter );
642 if (
Page *
const page =
d->currentPage() )
643 page->setKeyFilter( filter );
647 std::vector<QAbstractItemView*> result;
648 const unsigned int N =
count();
650 for (
unsigned int i = 0 ; i != N ; ++i )
651 if (
const Page *
const p =
d->page( i ) )
652 result.push_back( p->view() );
657 if (
Page *
const page =
d->currentPage() )
664 return d->tabWidget.count();
668 for (
unsigned int i = 0, end =
count() ; i != end ; ++i )
669 if (
const Page *
const p =
d->page( i ) )
670 if (
QTreeView *
const view = p->view() )
671 view->setSelectionMode( on ? QAbstractItemView::ExtendedSelection : QAbstractItemView::SingleSelection );
677 coll->addAction(
d->newAction->objectName(),
d->newAction );
678 for (
unsigned int i = 0 ; i < Private::NumPageActions ; ++i ) {
679 QAction * a =
d->currentPageActions[i];
685 return d->addView(
new Page( title,
id, text ),
d->currentPage() );
689 return d->addView(
new Page( group ), 0 );
694 page->setTemporary(
true );
696 d->tabWidget.setCurrentIndex(
d->tabWidget.count()-1 );
704 page->setFlatModel( flatModel );
705 page->setHierarchicalModel( hierarchicalModel );
707 connect( page, SIGNAL(titleChanged(
QString)),
708 q, SLOT(slotPageTitleChanged(
QString)) );
711 connect( page, SIGNAL(stringFilterChanged(
QString)),
712 q, SLOT(slotPageStringFilterChanged(
QString)) );
713 connect( page, SIGNAL(hierarchicalChanged(
bool)),
714 q, SLOT(slotPageHierarchyChanged(
bool)) );
716 if ( columnReference ) {
717 page->setColumnSizes( columnReference->columnSizes() );
718 page->setSortColumn( columnReference->sortColumn(), columnReference->sortOrder() );
722 const int tabIndex = tabWidget.addTab( page, page->title() );
723 tabWidget.setTabToolTip( tabIndex, page->toolTip() );
726 if ( previous != current )
727 currentIndexChanged( tabWidget.currentIndex() );
728 enableDisableCurrentPageActions();
730 emit
q->viewAdded( view );
745 Q_FOREACH(
const QString & group, groupList ) {
746 const KConfigGroup kcg( config, group );
763 config->deleteGroup( group );
765 for (
unsigned int i = 0, end =
count() ; i != end ; ++i ) {
766 if (
const Page *
const p =
d->page( i ) ) {
767 if ( p->isTemporary() )
769 KConfigGroup group( config,
QString().sprintf(
"View #%u", vg++ ) );
772 group.writeEntry(
"magic", 0xFA1AFE1U );
788 sb, SLOT(setChangeStringFilterEnabled(
bool)) );
790 sb, SLOT(setChangeKeyFilterEnabled(
bool)) );
793 #include "moc_tabwidget.cpp"
794 #include "tabwidget.moc"
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
static bool xconnect(const QObject *a, const char *signal, const QObject *b, const char *slot)
QString fromLatin1(const char *str, int size)
QStringList filter(const QString &str, Qt::CaseSensitivity cs) const
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
KAction * make_action_from_data(const action_data &data, QObject *parent)