1 /*
2     SPDX-FileCopyrightText: 2003-2008 Sebastian Trueg <trueg@k3b.org>
3     SPDX-FileCopyrightText: 2009-2010 Michal Malek <michalm@jabster.pl>
4     SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
5     SPDX-License-Identifier: GPL-2.0-or-later
6 */
7 
8 
9 
10 #include "k3bprojecttabwidget.h"
11 #include "k3bapplication.h"
12 #include "k3bprojectmanager.h"
13 
14 #include "k3bview.h"
15 #include "k3bdoc.h"
16 
17 #include <KLocalizedString>
18 #include <KIconLoader>
19 #include <KActionMenu>
20 
21 #include <QDebug>
22 #include <QMimeData>
23 #include <QUrl>
24 #include <QDragMoveEvent>
25 #include <QIcon>
26 #include <QDropEvent>
27 #include <QDragEnterEvent>
28 #include <QMouseEvent>
29 #include <QAction>
30 #include <QMenu>
31 #include <QTabBar>
32 
33 namespace {
34 
35     class ProjectData
36     {
37     public:
ProjectData()38         ProjectData()
39             : doc(0),
40             modified(false) {
41         }
42 
ProjectData(K3b::Doc * doc_)43         ProjectData( K3b::Doc* doc_ )
44             : doc(doc_),
45             modified(false) {
46         }
47 
48         // the project
49         K3b::Doc* doc;
50 
51         // is the project marked modified here
52         bool modified;
53     };
54 
55 } // namespace
56 
57 class K3b::ProjectTabWidget::Private
58 {
59 public:
60     KActionMenu* projectActionMenu;
61     QMap<Doc*, ProjectData> projectDataMap;
62 };
63 
64 
ProjectTabWidget(QWidget * parent)65 K3b::ProjectTabWidget::ProjectTabWidget( QWidget *parent )
66     : QTabWidget( parent ),
67       d( new Private )
68 {
69     setDocumentMode( true );
70     setTabsClosable( true );
71     setMovable( true );
72     tabBar()->setAcceptDrops(true);
73     tabBar()->installEventFilter( this );
74 
75     d->projectActionMenu = new KActionMenu( i18n("Project"), this );
76 
77     connect( this, SIGNAL(tabCloseRequested(int)), SLOT(slotTabCloseRequested(int)));
78 }
79 
80 
~ProjectTabWidget()81 K3b::ProjectTabWidget::~ProjectTabWidget()
82 {
83     delete d;
84 }
85 
86 
addTab(Doc * doc)87 void K3b::ProjectTabWidget::addTab( Doc* doc )
88 {
89     QTabWidget::addTab( doc->view(), doc->URL().fileName() );
90     connect( k3bappcore->projectManager(), SIGNAL(projectSaved(K3b::Doc*)), this, SLOT(slotDocSaved(K3b::Doc*)) );
91     connect( doc, SIGNAL(changed(K3b::Doc*)), this, SLOT(slotDocChanged(K3b::Doc*)) );
92 
93     d->projectDataMap[doc] = ProjectData( doc );
94 
95     if( doc->isModified() )
96         slotDocChanged( doc );
97     else
98         slotDocSaved( doc );
99 }
100 
101 
removeTab(Doc * doc)102 void K3b::ProjectTabWidget::removeTab( Doc* doc )
103 {
104     if( doc != 0 ) {
105         QTabWidget::removeTab( indexOf( doc->view() ) );
106     }
107 }
108 
109 
setCurrentTab(Doc * doc)110 void K3b::ProjectTabWidget::setCurrentTab( Doc* doc )
111 {
112     if( doc != 0 ) {
113         setCurrentWidget( doc->view() );
114         doc->view()->setFocus();
115     }
116 }
117 
118 
currentTab() const119 K3b::Doc* K3b::ProjectTabWidget::currentTab() const
120 {
121     QWidget* widget = currentWidget();
122     if( K3b::View* view = qobject_cast<K3b::View*>(widget) )
123         return view->doc();
124     else
125         return 0;
126 }
127 
128 
addAction(QAction * action)129 void K3b::ProjectTabWidget::addAction( QAction* action )
130 {
131     d->projectActionMenu->addAction( action );
132 }
133 
134 
projectAt(const QPoint & pos) const135 K3b::Doc* K3b::ProjectTabWidget::projectAt( const QPoint& pos ) const
136 {
137     int tabPos = tabBar()->tabAt(pos);
138     if( tabPos != -1 )
139     {
140         QWidget *w = widget(tabPos);
141         if(View* view = qobject_cast<View*>(w) )
142             return view->doc();
143     }
144     return 0;
145 }
146 
147 
eventFilter(QObject * o,QEvent * e)148 bool K3b::ProjectTabWidget::eventFilter( QObject* o, QEvent* e )
149 {
150     if( o == tabBar() ) {
151         if( e->type() == QEvent::MouseButtonPress ) {
152             QMouseEvent* me = static_cast<QMouseEvent*>(e);
153             if( me->button() == Qt::RightButton ) {
154                 if( projectAt( me->pos() ) ) {
155                     int tabPos = tabBar()->tabAt(me->pos());
156                     if(tabPos!=-1){
157                         setCurrentIndex(tabPos);
158                         // show the popup menu
159                         d->projectActionMenu->menu()->exec( me->globalPos() );
160                     }
161                 }
162                 return true;
163             }
164         }
165 
166         else if( e->type() == QEvent::DragEnter ) {
167             QDragEnterEvent* de = static_cast<QDragEnterEvent*>(e);
168             de->setAccepted( de->mimeData()->hasUrls() );
169             return true;
170         }
171 
172         else if( e->type() == QEvent::DragMove ) {
173             QDragMoveEvent* de = static_cast<QDragMoveEvent*>(e);
174             de->setAccepted( projectAt(de->pos()) != 0 );
175             return true;
176         }
177 
178         else if( e->type() == QEvent::Drop ) {
179             QDropEvent* de = static_cast<QDropEvent*>(e);
180             if( de->mimeData()->hasUrls() ) {
181                 if( Doc* doc = projectAt( de->pos() ) ) {
182                     QList<QUrl> urls;
183                     Q_FOREACH( const QUrl& url, de->mimeData()->urls() ) {
184                         urls.append( url );
185                     }
186                     qobject_cast<View*>(doc->view())->addUrls( urls );
187                 }
188             }
189             return true;
190         }
191     }
192 
193     return QTabWidget::eventFilter( o, e );
194 }
195 
196 
slotDocChanged(K3b::Doc * doc)197 void K3b::ProjectTabWidget::slotDocChanged( K3b::Doc* doc )
198 {
199     // we need to cache the icon changes since the changed() signal will be emitted very often
200     if( !d->projectDataMap[doc].modified ) {
201         setTabIcon( indexOf( doc->view() ), QIcon::fromTheme( "document-save" ) );
202         d->projectDataMap[doc].modified = true;
203 
204         // we need this one for the session management
205         setTabText( indexOf( doc->view() ), doc->URL().fileName() );
206     }
207 }
208 
209 
slotDocSaved(K3b::Doc * doc)210 void K3b::ProjectTabWidget::slotDocSaved( K3b::Doc* doc )
211 {
212     setTabIcon( indexOf( doc->view() ), QIcon() );
213     setTabText( indexOf( doc->view() ), doc->URL().fileName() );
214 }
215 
216 
slotTabCloseRequested(int index)217 void K3b::ProjectTabWidget::slotTabCloseRequested( int index )
218 {
219     QWidget* w = widget( index );
220     if( View* view = qobject_cast<View*>(w) ) {
221         emit tabCloseRequested( view->doc() );
222     }
223 }
224 
225 
226 
227