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