1 /****************************************************************************************
2  * Copyright (c) 2010 Rainer Sigle <rainer.sigle@web.de>                                *
3  *                                                                                      *
4  * This program is free software; you can redistribute it and/or modify it under        *
5  * the terms of the GNU General Public License as published by the Free Software        *
6  * Foundation; either version 2 of the License, or (at your option) any later           *
7  * version.                                                                             *
8  *                                                                                      *
9  * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
10  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
11  * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
12  *                                                                                      *
13  * You should have received a copy of the GNU General Public License along with         *
14  * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
15  ****************************************************************************************/
16 
17 #include "TabsView.h"
18 #include "TabsItem.h"
19 #include "core/support/Debug.h"
20 #include "PaletteHandler.h"
21 #include "widgets/PrettyTreeView.h"
22 
23 #include <KTextBrowser>
24 #include <Plasma/ScrollBar>
25 #include <Plasma/TextBrowser>
26 
27 #include <QGraphicsLinearLayout>
28 
29 // Subclassed to override the access level of some methods.
30 // The TabsTreeView and the TabsView are so highly coupled that this is acceptable, imo.
31 class TabsTreeView : public Amarok::PrettyTreeView
32 {
33     public:
TabsTreeView(QWidget * parent=0)34         TabsTreeView( QWidget *parent = 0 )
35             : Amarok::PrettyTreeView( parent )
36         {
37             setAttribute( Qt::WA_NoSystemBackground );
38             viewport()->setAutoFillBackground( false );
39 
40             setHeaderHidden( true );
41             setIconSize( QSize( 36, 36 ) );
42             setDragDropMode( QAbstractItemView::DragOnly );
43             setSelectionMode( QAbstractItemView::SingleSelection );
44             setSelectionBehavior( QAbstractItemView::SelectItems );
45             setAnimated( true );
46             setRootIsDecorated( false );
47             setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
48             setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
49             setFixedWidth( 48 );
50 
51         }
52     protected:
53 
54         // Override access level to make it public. Only visible to the TabsView.
55         // Used for context menu methods.
selectedIndexes() const56         QModelIndexList selectedIndexes() const { return PrettyTreeView::selectedIndexes(); }
57 };
58 
59 
TabsView(QGraphicsWidget * parent)60 TabsView::TabsView( QGraphicsWidget *parent )
61     : QGraphicsProxyWidget( parent )
62 {
63     // tree view which holds the collection of fetched tabs
64     m_treeView = new TabsTreeView( 0 );
65     connect( m_treeView, SIGNAL(clicked(QModelIndex)),
66              this, SLOT(itemClicked(QModelIndex)) );
67 
68     m_model = new QStandardItemModel();
69     m_model->setColumnCount( 1 );
70     m_treeView->setModel( m_model );
71 
72     m_treeProxy = new QGraphicsProxyWidget( this );
73     m_treeProxy->setWidget( m_treeView );
74 
75     // the textbrowser widget to display the tabs
76     m_tabTextBrowser = new Plasma::TextBrowser( );
77     KTextBrowser *browserWidget = m_tabTextBrowser->nativeWidget();
78     browserWidget->setFrameShape( QFrame::StyledPanel );
79     browserWidget->setAttribute( Qt::WA_NoSystemBackground );
80     browserWidget->setOpenExternalLinks( true );
81     browserWidget->setUndoRedoEnabled( true );
82     browserWidget->setAutoFillBackground( false );
83     browserWidget->setWordWrapMode( QTextOption::NoWrap );
84     browserWidget->viewport()->setAutoFillBackground( true );
85     browserWidget->viewport()->setAttribute( Qt::WA_NoSystemBackground );
86     browserWidget->setTextInteractionFlags( Qt::TextBrowserInteraction | Qt::TextSelectableByKeyboard );
87 
88     QScrollBar *treeScrollBar = m_treeView->verticalScrollBar();
89     m_scrollBar = new Plasma::ScrollBar( this );
90     m_scrollBar->setFocusPolicy( Qt::NoFocus );
91 
92     // synchronize scrollbars
93     connect( treeScrollBar, SIGNAL(rangeChanged(int,int)), SLOT(slotScrollBarRangeChanged(int,int)) );
94     connect( treeScrollBar, SIGNAL(valueChanged(int)), m_scrollBar, SLOT(setValue(int)) );
95     connect( m_scrollBar, SIGNAL(valueChanged(int)), treeScrollBar, SLOT(setValue(int)) );
96     m_scrollBar->setRange( treeScrollBar->minimum(), treeScrollBar->maximum() );
97     m_scrollBar->setPageStep( treeScrollBar->pageStep() );
98     m_scrollBar->setSingleStep( treeScrollBar->singleStep() );
99 
100     // arrange textbrowser and treeview in a horizontal layout
101     QGraphicsLinearLayout *layout = new QGraphicsLinearLayout( Qt::Horizontal );
102     layout->addItem( m_treeProxy );
103     layout->addItem( m_scrollBar );
104     layout->addItem( m_tabTextBrowser );
105     layout->setSpacing( 2 );
106     layout->setContentsMargins( 0, 0, 0, 0 );
107     setLayout( layout );
108     setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
109     updateScrollBarVisibility();
110 }
111 
~TabsView()112 TabsView::~TabsView()
113 {
114     delete m_model;
115     delete m_treeProxy;
116 }
117 
118 void
appendTab(TabsItem * tabsItem)119 TabsView::appendTab( TabsItem *tabsItem  )
120 {
121     if( tabsItem )
122         m_model->appendRow( tabsItem );
123 }
124 
125 void
clear()126 TabsView::clear()
127 {
128     qDeleteAll( m_model->findItems(QLatin1String("*"), Qt::MatchWildcard) );
129     m_model->clear();
130 }
131 
132 void
clearTabBrowser()133 TabsView::clearTabBrowser()
134 {
135     m_tabTextBrowser->nativeWidget()->clear();
136 }
137 
138 void
showTab(TabsItem * tab)139 TabsView::showTab( TabsItem *tab )
140 {
141     if( tab )
142     {
143         QString tabText = tab->getTabData();
144         if( tabText.length() > 0 )
145         {
146             tabText.replace( '\n', "<br></br>", Qt::CaseInsensitive );
147 
148             QFont tabFont( "monospace");
149             tabFont.setStyleHint( QFont::Courier );
150             tabFont.setStyleStrategy( QFont::PreferAntialias );
151             tabFont.setWeight( QFont::Normal );
152             tabFont.setPointSize( QFont().pointSize() );
153 
154             QFont headingFont( "sans-serif" );
155             headingFont.setPointSize( tabFont.pointSize() + 2 );
156             headingFont.setStyleHint( QFont::SansSerif );
157             headingFont.setStyleStrategy( QFont::PreferAntialias );
158             headingFont.setWeight( QFont::Black );
159             QString linkColor = The::paletteHandler()->palette().link().color().name();
160             QString textColor = The::paletteHandler()->palette().text().color().name();
161             int headingWeight = 600;
162 
163             QString htmlData = "<html>";
164                     htmlData += "<body style=\"font-family:'" + tabFont.family() + "';";
165                     htmlData += "font-size:" + QString::number( tabFont.pointSize() ) + "pt;";
166                     htmlData += "font-weight:" + QString::number( tabFont.weight() ) + ';';
167                     htmlData += "color:" + textColor + ";\">";
168 
169                     // tab heading + tab source
170                     htmlData += "<p><span style=\"font-family:'" + headingFont.family() + "';";
171                     htmlData += "font-size:" + QString::number( headingFont.pointSize() ) + "pt;";
172                     htmlData += "font-weight:" + QString::number( headingWeight ) + ";\">";
173                     htmlData += tab->getTabTitle();
174                     htmlData += " (" + i18nc( "Guitar tablature", "tab provided from: " ) + "<a href=\"" + tab->getTabUrl() + "\">";
175                     htmlData += "<span style=\"text-decoration: underline; color:" + linkColor + ";\">";
176                     htmlData += tab->getTabSource() + "</a>";
177                     htmlData += ")</span></p>";
178 
179                     // tab data
180                     htmlData += tabText + "</body></html>";
181 
182             // backup current scrollbar position
183             QScrollBar *vbar = m_tabTextBrowser->nativeWidget()->verticalScrollBar();
184             int scrollPosition = vbar->isVisible() ? vbar->value() : vbar->minimum();
185 
186             m_tabTextBrowser->nativeWidget()->setHtml( htmlData );
187 
188             // re-apply scrollbar position
189             vbar->setSliderPosition( scrollPosition );
190         }
191     }
192 }
193 
194 void
itemClicked(const QModelIndex & index)195 TabsView::itemClicked( const QModelIndex &index )
196 {
197     const QStandardItemModel *itemModel = static_cast<QStandardItemModel*>( m_treeView->model() );
198 
199     QStandardItem *item = itemModel->itemFromIndex( index );
200     TabsItem *tab = dynamic_cast<TabsItem*>( item );
201     if( tab )
202         showTab( tab );
203 }
204 
205 void
resizeEvent(QGraphicsSceneResizeEvent * event)206 TabsView::resizeEvent( QGraphicsSceneResizeEvent *event )
207 {
208     QGraphicsWidget::resizeEvent( event );
209 }
210 
211 void
slotScrollBarRangeChanged(int min,int max)212 TabsView::slotScrollBarRangeChanged( int min, int max )
213 {
214     m_scrollBar->setRange( min, max );
215     m_scrollBar->setPageStep( m_treeView->verticalScrollBar()->pageStep() );
216     m_scrollBar->setSingleStep( m_treeView->verticalScrollBar()->singleStep() );
217     updateScrollBarVisibility();
218 }
219 
220 void
updateScrollBarVisibility()221 TabsView::updateScrollBarVisibility()
222 {
223     QGraphicsLinearLayout *lo = static_cast<QGraphicsLinearLayout*>( layout() );
224     if( m_scrollBar->maximum() == 0 )
225     {
226         if( lo->count() > 2 && lo->itemAt( 1 ) == m_scrollBar )
227         {
228             lo->removeAt( 1 );
229             m_scrollBar->hide();
230         }
231     }
232     else if( lo->count() == 2 )
233     {
234         lo->insertItem( 1, m_scrollBar );
235         m_scrollBar->show();
236     }
237 }
238 
239 
240 #include <TabsView.moc>
241 
242