xref: /glogg/src/tabbedcrawlerwidget.cpp (revision 702af59ea138e3124b906092de415e3601c74d3e)
1 /*
2  * Copyright (C) 2014, 2015 Nicolas Bonnefon and other contributors
3  *
4  * This file is part of glogg.
5  *
6  * glogg is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * glogg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with glogg.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "tabbedcrawlerwidget.h"
21 
22 #include <QKeyEvent>
23 #include <QLabel>
24 
25 #include "crawlerwidget.h"
26 
27 #include "log.h"
28 
29 TabbedCrawlerWidget::TabbedCrawlerWidget() : QTabWidget(),
30     olddata_icon_( ":/images/olddata_icon.png" ),
31     newdata_icon_( ":/images/newdata_icon.png" ),
32     newfiltered_icon_( ":/images/newfiltered_icon.png" ),
33     myTabBar_()
34 {
35 #ifdef WIN32
36     myTabBar_.setStyleSheet( "QTabBar::tab {\
37             height: 20px; "
38             "} "
39             "QTabBar::close-button {\
40               height: 6px; width: 6px;\
41               subcontrol-origin: padding;\
42               subcontrol-position: left;\
43              }" );
44 #else
45     // On GTK style, it looks better with a smaller font
46     myTabBar_.setStyleSheet(
47             "QTabBar::tab {"
48             " height: 20px; "
49             " font-size: 9pt; "
50             "} "
51             "QTabBar::close-button {\
52               height: 6px; width: 6px;\
53               subcontrol-origin: padding;\
54               subcontrol-position: left;\
55              }" );
56 #endif
57     setTabBar( &myTabBar_ );
58     myTabBar_.hide();
59 
60 }
61 
62 // I know hiding non-virtual functions from the base class is bad form
63 // and I do it here out of pure laziness: I don't want to encapsulate
64 // QTabBar with all signals and all just to implement this very simple logic.
65 // Maybe one day that should be done better...
66 
67 int TabbedCrawlerWidget::addTab( QWidget* page, const QString& label )
68 {
69     int index = QTabWidget::addTab( page, label );
70 
71     if ( auto crawler = dynamic_cast<CrawlerWidget*>( page ) ) {
72         // Mmmmhhhh... new Qt5 signal syntax create tight coupling between
73         // us and the sender, baaaaad....
74 
75         // Listen for a changing data status:
76         connect( crawler, &CrawlerWidget::dataStatusChanged,
77                 [ this, index ]( DataStatus status ) { setTabDataStatus( index, status ); } );
78     }
79 
80     // Display the icon
81     QLabel* icon_label = new QLabel();
82     icon_label->setPixmap( olddata_icon_.pixmap( 11, 12 ) );
83     icon_label->setAlignment( Qt::AlignCenter );
84     myTabBar_.setTabButton( index, QTabBar::RightSide, icon_label );
85 
86     LOG(logDEBUG) << "addTab, count = " << count();
87     LOG(logDEBUG) << "width = " << olddata_icon_.pixmap( 11, 12 ).devicePixelRatio();
88 
89     if ( count() > 1 )
90         myTabBar_.show();
91 
92     return index;
93 }
94 
95 void TabbedCrawlerWidget::removeTab( int index )
96 {
97     QTabWidget::removeTab( index );
98 
99     if ( count() <= 1 )
100         myTabBar_.hide();
101 }
102 
103 void TabbedCrawlerWidget::mouseReleaseEvent( QMouseEvent *event)
104 {
105     LOG(logDEBUG) << "TabbedCrawlerWidget::mouseReleaseEvent";
106 
107     if (event->button() == Qt::MidButton)
108     {
109         int tab = this->myTabBar_.tabAt( event->pos() );
110         if (-1 != tab)
111         {
112             emit tabCloseRequested( tab );
113         }
114     }
115 }
116 
117 void TabbedCrawlerWidget::keyPressEvent( QKeyEvent* event )
118 {
119     LOG(logDEBUG) << "TabbedCrawlerWidget::keyPressEvent";
120 
121     char c = ( event->text() )[0].toLatin1();
122     Qt::KeyboardModifiers mod = event->modifiers();
123 
124     // Ctrl + tab
125     if ( mod == Qt::ControlModifier && c == '\t' ) {
126         setCurrentIndex( ( currentIndex() + 1 ) % count() );
127     }
128     // Ctrl + shift + tab
129     else if ( mod == ( Qt::ControlModifier | Qt::ShiftModifier ) && c == '\t' ) {
130         setCurrentIndex( ( currentIndex() + 1 ) % count() );
131     }
132     // Ctrl + numbers
133     else if ( mod == Qt::ControlModifier && ( c >= '1' && c <= '8' ) ) {
134         LOG(logDEBUG) << "number " << c;
135         int new_index = c - '0';
136         if ( new_index <= count() )
137             setCurrentIndex( new_index - 1 );
138     }
139     // Ctrl + 9
140     else if ( mod == Qt::ControlModifier && c == '9' ) {
141         LOG(logDEBUG) << "last";
142         setCurrentIndex( count() - 1 );
143     }
144     else if ( mod == Qt::ControlModifier && (c == 'q' || c == 'w') ) {
145         LOG(logDEBUG) << "Close tab " << currentIndex();
146         emit tabCloseRequested( currentIndex() );
147     }
148     else {
149         QTabWidget::keyPressEvent( event );
150     }
151 }
152 
153 void TabbedCrawlerWidget::setTabDataStatus( int index, DataStatus status )
154 {
155     LOG(logDEBUG) << "TabbedCrawlerWidget::setTabDataStatus " << index;
156 
157     QLabel* icon_label = dynamic_cast<QLabel*>(
158             myTabBar_.tabButton( index, QTabBar::RightSide ) );
159 
160     if ( icon_label ) {
161         const QIcon* icon;
162         switch ( status ) {
163             case DataStatus::OLD_DATA:
164                 icon = &olddata_icon_;
165                 break;
166             case DataStatus::NEW_DATA:
167                 icon = &newdata_icon_;
168                 break;
169             case DataStatus::NEW_FILTERED_DATA:
170                 icon = &newfiltered_icon_;
171                 break;
172         }
173         icon_label->setPixmap ( icon->pixmap(12,12) );
174     }
175 }
176