1 | /* This file is part of the KDE project |
2 | Copyright (C) 2007 -2010 Dag Andersen <danders@get2net.dk> |
3 | |
4 | This library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Library General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2 of the License, or (at your option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Library General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to |
16 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
17 | * Boston, MA 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "kptviewlist.h" |
21 | |
22 | #include <QString> |
23 | #include <QStringList> |
24 | #include <QTreeWidget> |
25 | #include <QTreeWidgetItem> |
26 | #include <QItemDelegate> |
27 | #include <QStyle> |
28 | #include <QHeaderView> |
29 | #include <QBrush> |
30 | #include <QContextMenuEvent> |
31 | #include <QTimer> |
32 | |
33 | #include <kmenu.h> |
34 | #include <kmessagebox.h> |
35 | #include <kcombobox.h> |
36 | |
37 | #include <KoIcon.h> |
38 | #include "KoDocument.h" |
39 | |
40 | #include "kptviewbase.h" |
41 | #include "kptmaindocument.h" |
42 | #include "kptviewlistdialog.h" |
43 | #include "kptviewlistdocker.h" |
44 | #include "kptschedulemodel.h" |
45 | #include <kptdebug.h> |
46 | |
47 | #include <assert.h> |
48 | |
49 | |
50 | namespace KPlato |
51 | { |
52 | |
53 | // <Code mostly nicked from qt designer ;)> |
54 | class ViewCategoryDelegate : public QItemDelegate |
55 | { |
56 | public: |
57 | ViewCategoryDelegate( QObject *parent, QTreeView *view ) |
58 | : QItemDelegate( parent ), |
59 | m_view( view ) |
60 | {} |
61 | |
62 | QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; |
63 | virtual void paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const; |
64 | |
65 | private: |
66 | QTreeView *m_view; |
67 | }; |
68 | |
69 | QSize ViewCategoryDelegate::sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const |
70 | { |
71 | const QAbstractItemModel * model = index.model(); |
72 | Q_ASSERT( model ); |
73 | if ( model->parent( index ).isValid() ) { |
74 | return QItemDelegate::sizeHint( option, index ); |
75 | } |
76 | return QItemDelegate::sizeHint( option, index ).expandedTo( QSize( 0, 16 ) ); |
77 | } |
78 | |
79 | void ViewCategoryDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const |
80 | { |
81 | const QAbstractItemModel * model = index.model(); |
82 | Q_ASSERT( model ); |
83 | |
84 | if ( !model->parent( index ).isValid() ) { |
85 | // this is a top-level item. |
86 | QStyleOptionButton buttonOption; |
87 | buttonOption.state = option.state; |
88 | |
89 | buttonOption.rect = option.rect; |
90 | buttonOption.palette = option.palette; |
91 | buttonOption.features = QStyleOptionButton::None; |
92 | m_view->style() ->drawControl( QStyle::CE_PushButton, &buttonOption, painter, m_view ); |
93 | |
94 | QStyleOption branchOption; |
95 | static const int i = 9; // ### hardcoded in qcommonstyle.cpp |
96 | QRect r = option.rect; |
97 | branchOption.rect = QRect( r.left() + i / 2, r.top() + ( r.height() - i ) / 2, i, i ); |
98 | branchOption.palette = option.palette; |
99 | branchOption.state = QStyle::State_Children; |
100 | |
101 | if ( m_view->isExpanded( index ) ) |
102 | branchOption.state |= QStyle::State_Open; |
103 | |
104 | m_view->style() ->drawPrimitive( QStyle::PE_IndicatorBranch, &branchOption, painter, m_view ); |
105 | |
106 | // draw text |
107 | QRect textrect = QRect( r.left() + i * 2, r.top(), r.width() - ( ( 5 * i ) / 2 ), r.height() ); |
108 | QString text = elidedText( option.fontMetrics, textrect.width(), Qt::ElideMiddle, |
109 | model->data( index, Qt::DisplayRole ).toString() ); |
110 | m_view->style() ->drawItemText( painter, textrect, Qt::AlignLeft|Qt::AlignVCenter, |
111 | option.palette, m_view->isEnabled(), text ); |
112 | |
113 | } else { |
114 | QItemDelegate::paint( painter, option, index ); |
115 | } |
116 | |
117 | } |
118 | |
119 | ViewListItem::ViewListItem( const QString &tag, const QStringList &strings, int type ) |
120 | : QTreeWidgetItem( strings, type ), |
121 | m_tag( tag ) |
122 | { |
123 | } |
124 | |
125 | ViewListItem::ViewListItem( QTreeWidget *parent, const QString &tag, const QStringList &strings, int type ) |
126 | : QTreeWidgetItem( parent, strings, type ), |
127 | m_tag( tag ) |
128 | { |
129 | } |
130 | |
131 | ViewListItem::ViewListItem( QTreeWidgetItem *parent, const QString &tag, const QStringList &strings, int type ) |
132 | : QTreeWidgetItem( parent, strings, type ), |
133 | m_tag( tag ) |
134 | { |
135 | } |
136 | |
137 | void ViewListItem::setReadWrite( bool rw ) |
138 | { |
139 | if ( type() == ItemType_SubView ) { |
140 | static_cast<ViewBase*>( view() )->updateReadWrite( rw ); |
141 | } |
142 | } |
143 | |
144 | void ViewListItem::setView( ViewBase *view ) |
145 | { |
146 | setData( 0, ViewListItem::DataRole_View, qVariantFromValue(static_cast<QObject*>( view ) ) ); |
147 | } |
148 | |
149 | ViewBase *ViewListItem::view() const |
150 | { |
151 | if ( data(0, ViewListItem::DataRole_View ).isValid() ) { |
152 | return static_cast<ViewBase*>( data(0, ViewListItem::DataRole_View ).value<QObject*>() ); |
153 | } |
154 | return 0; |
155 | } |
156 | |
157 | void ViewListItem::setDocument( KoDocument *doc ) |
158 | { |
159 | setData( 0, ViewListItem::DataRole_Document, qVariantFromValue(static_cast<QObject*>( doc ) ) ); |
160 | } |
161 | |
162 | KoDocument *ViewListItem::document() const |
163 | { |
164 | if ( data(0, ViewListItem::DataRole_Document ).isValid() ) { |
165 | return static_cast<KoDocument*>( data(0, ViewListItem::DataRole_Document ).value<QObject*>() ); |
166 | } |
167 | return 0; |
168 | } |
169 | |
170 | QString ViewListItem::viewType() const |
171 | { |
172 | if ( type() != ItemType_SubView ) { |
173 | return QString(); |
174 | } |
175 | QString name = view()->metaObject()->className(); |
176 | if ( name.contains( ':' ) ) { |
177 | name = name.remove( 0, name.lastIndexOf( ':' ) + 1 ); |
178 | } |
179 | return name; |
180 | } |
181 | |
182 | void ViewListItem::save( QDomElement &element ) const |
183 | { |
184 | element.setAttribute( "itemtype" , type() ); |
185 | element.setAttribute( "tag" , tag() ); |
186 | |
187 | if ( type() == ItemType_SubView ) { |
188 | element.setAttribute( "viewtype" , viewType() ); |
189 | element.setAttribute( "name" , m_viewinfo.name == text( 0 ) ? "" : text( 0 ) ); |
190 | element.setAttribute( "tooltip" , m_viewinfo.tip == toolTip( 0 ) ? TIP_USE_DEFAULT_TEXT : toolTip( 0 ) ); |
191 | } else if ( type() == ItemType_Category ) { |
192 | kDebug(planDbg())<<text(0)<<m_viewinfo.name; |
193 | element.setAttribute( "name" , text( 0 ) == m_viewinfo.name ? "" : text( 0 ) ); |
194 | element.setAttribute( "tooltip" , toolTip( 0 ).isEmpty() ? TIP_USE_DEFAULT_TEXT : toolTip( 0 ) ); |
195 | } |
196 | } |
197 | |
198 | ViewListTreeWidget::ViewListTreeWidget( QWidget *parent ) |
199 | : QTreeWidget( parent ) |
200 | { |
201 | setWhatsThis( i18nc( "@info:whatsthis" , |
202 | "<para>This is the list of available views and editors.</para>" |
203 | "<para>You can configure the list by using the context menu:" |
204 | "<list>" |
205 | "<item>Rename categories or views</item>" |
206 | "<item>Configure. Move, remove, rename or edit tool tip for categories or views</item>" |
207 | "<item>Insert categories and views</item>" |
208 | "</list></para>" |
209 | ) ); |
210 | |
211 | header() ->hide(); |
212 | setRootIsDecorated( false ); |
213 | setItemDelegate( new ViewCategoryDelegate( this, this ) ); |
214 | setItemsExpandable( true ); |
215 | setSelectionMode( QAbstractItemView::SingleSelection ); |
216 | |
217 | setDragDropMode( QAbstractItemView::InternalMove ); |
218 | |
219 | //setContextMenuPolicy( Qt::ActionsContextMenu ); |
220 | |
221 | connect( this, SIGNAL(itemPressed(QTreeWidgetItem*,int)), SLOT(handleMousePress(QTreeWidgetItem*)) ); |
222 | } |
223 | |
224 | void ViewListTreeWidget::drawRow( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const |
225 | { |
226 | QTreeWidget::drawRow( painter, option, index ); |
227 | } |
228 | |
229 | void ViewListTreeWidget::handleMousePress( QTreeWidgetItem *item ) |
230 | { |
231 | //kDebug(planDbg()); |
232 | if ( item == 0 ) |
233 | return ; |
234 | |
235 | if ( item->parent() == 0 ) { |
236 | setItemExpanded( item, !isItemExpanded( item ) ); |
237 | return ; |
238 | } |
239 | } |
240 | void ViewListTreeWidget::mousePressEvent ( QMouseEvent *event ) |
241 | { |
242 | if ( event->button() == Qt::RightButton ) { |
243 | QTreeWidgetItem *item = itemAt( event->pos() ); |
244 | if ( item && item->type() == ViewListItem::ItemType_Category ) { |
245 | setCurrentItem( item ); |
246 | emit customContextMenuRequested( event->pos() ); |
247 | event->accept(); |
248 | return; |
249 | } |
250 | } |
251 | QTreeWidget::mousePressEvent( event ); |
252 | } |
253 | |
254 | void ViewListTreeWidget::save( QDomElement &element ) const |
255 | { |
256 | int cnt = topLevelItemCount(); |
257 | if ( cnt == 0 ) { |
258 | return; |
259 | } |
260 | QDomElement cs = element.ownerDocument().createElement( "categories" ); |
261 | element.appendChild( cs ); |
262 | for ( int i = 0; i < cnt; ++i ) { |
263 | ViewListItem *itm = static_cast<ViewListItem*>( topLevelItem( i ) ); |
264 | if ( itm->type() != ViewListItem::ItemType_Category ) { |
265 | continue; |
266 | } |
267 | QDomElement c = cs.ownerDocument().createElement( "category" ); |
268 | cs.appendChild( c ); |
269 | emit const_cast<ViewListTreeWidget*>( this )->updateViewInfo( itm ); |
270 | itm->save( c ); |
271 | for ( int j = 0; j < itm->childCount(); ++j ) { |
272 | ViewListItem *vi = static_cast<ViewListItem*>( itm->child( j ) ); |
273 | if ( vi->type() != ViewListItem::ItemType_SubView ) { |
274 | continue; |
275 | } |
276 | QDomElement el = c.ownerDocument().createElement( "view" ); |
277 | c.appendChild( el ); |
278 | emit const_cast<ViewListTreeWidget*>( this )->updateViewInfo( vi ); |
279 | vi->save( el ); |
280 | QDomElement elm = el.ownerDocument().createElement( "settings" ); |
281 | el.appendChild( elm ); |
282 | static_cast<ViewBase*>( vi->view() )->saveContext( elm ); |
283 | } |
284 | } |
285 | } |
286 | |
287 | |
288 | // </Code mostly nicked from qt designer ;)> |
289 | |
290 | void ViewListTreeWidget::startDrag( Qt::DropActions supportedActions ) |
291 | { |
292 | QModelIndexList indexes = selectedIndexes(); |
293 | if ( indexes.count() == 1 ) { |
294 | ViewListItem *item = static_cast<ViewListItem*>( itemFromIndex( indexes.at( 0 ) ) ); |
295 | Q_ASSERT( item ); |
296 | QTreeWidgetItem *root = invisibleRootItem(); |
297 | int count = root->childCount(); |
298 | if ( item && item->type() == ViewListItem::ItemType_Category ) { |
299 | root->setFlags( root->flags() | Qt::ItemIsDropEnabled ); |
300 | for ( int i = 0; i < count; ++i ) { |
301 | QTreeWidgetItem * ch = root->child( i ); |
302 | ch->setFlags( ch->flags() & ~Qt::ItemIsDropEnabled ); |
303 | } |
304 | } else if ( item ) { |
305 | root->setFlags( root->flags() & ~Qt::ItemIsDropEnabled ); |
306 | for ( int i = 0; i < count; ++i ) { |
307 | QTreeWidgetItem * ch = root->child( i ); |
308 | ch->setFlags( ch->flags() | Qt::ItemIsDropEnabled ); |
309 | } |
310 | } |
311 | } |
312 | QTreeWidget::startDrag( supportedActions ); |
313 | } |
314 | |
315 | void ViewListTreeWidget::dropEvent( QDropEvent *event ) |
316 | { |
317 | QTreeWidget::dropEvent( event ); |
318 | if ( event->isAccepted() ) { |
319 | emit modified(); |
320 | } |
321 | } |
322 | |
323 | ViewListItem *ViewListTreeWidget::findCategory( const QString &cat ) |
324 | { |
325 | QTreeWidgetItem * item; |
326 | int cnt = topLevelItemCount(); |
327 | for ( int i = 0; i < cnt; ++i ) { |
328 | item = topLevelItem( i ); |
329 | if ( static_cast<ViewListItem*>(item)->tag() == cat ) |
330 | return static_cast<ViewListItem*>(item); |
331 | } |
332 | return 0; |
333 | } |
334 | |
335 | ViewListItem *ViewListTreeWidget::category( const KoView *view ) const |
336 | { |
337 | QTreeWidgetItem * item; |
338 | int cnt = topLevelItemCount(); |
339 | for ( int i = 0; i < cnt; ++i ) { |
340 | item = topLevelItem( i ); |
341 | for ( int c = 0; c < item->childCount(); ++c ) { |
342 | if ( view == static_cast<ViewListItem*>( item->child( c ) )->view() ) { |
343 | return static_cast<ViewListItem*>( item ); |
344 | } |
345 | } |
346 | } |
347 | return 0; |
348 | } |
349 | |
350 | //----------------------- |
351 | ViewListWidget::ViewListWidget( MainDocument *part, QWidget *parent )//QString name, KXmlGuiWindow *parent ) |
352 | : QWidget( parent ), |
353 | m_part( part ), |
354 | m_prev( 0 ), |
355 | m_temp( 0 ) |
356 | { |
357 | setObjectName("ViewListWidget" ); |
358 | m_viewlist = new ViewListTreeWidget( this ); |
359 | m_viewlist->setEditTriggers( QAbstractItemView::NoEditTriggers ); |
360 | connect(m_viewlist, SIGNAL(modified()), this, SIGNAL(modified())); |
361 | |
362 | m_currentSchedule = new KComboBox( this ); |
363 | m_model.setFlat( true ); |
364 | |
365 | m_sfModel.setFilterKeyColumn ( ScheduleModel::ScheduleScheduled ); |
366 | m_sfModel.setFilterRole( Qt::EditRole ); |
367 | m_sfModel.setFilterFixedString( "true" ); |
368 | m_sfModel.setDynamicSortFilter ( true ); |
369 | m_sfModel.setSourceModel( &m_model ); |
370 | m_currentSchedule->setModel( &m_sfModel ); |
371 | |
372 | QVBoxLayout *l = new QVBoxLayout( this ); |
373 | l->setMargin( 0 ); |
374 | l->addWidget( m_viewlist ); |
375 | l->addWidget( m_currentSchedule ); |
376 | |
377 | connect( m_viewlist, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), SLOT(slotActivated(QTreeWidgetItem*,QTreeWidgetItem*)) ); |
378 | |
379 | connect( m_viewlist, SIGNAL(itemChanged(QTreeWidgetItem*,int)), SLOT(slotItemChanged(QTreeWidgetItem*,int)) ); |
380 | |
381 | setupContextMenus(); |
382 | |
383 | connect( m_currentSchedule, SIGNAL(activated(int)), SLOT(slotCurrentScheduleChanged(int)) ); |
384 | |
385 | connect( &m_model, SIGNAL(scheduleManagerAdded(ScheduleManager*)), SLOT(slotScheduleManagerAdded(ScheduleManager*)) ); |
386 | |
387 | connect( m_viewlist, SIGNAL(updateViewInfo(ViewListItem*)), SIGNAL(updateViewInfo(ViewListItem*)) ); |
388 | } |
389 | |
390 | ViewListWidget::~ViewListWidget() |
391 | { |
392 | } |
393 | |
394 | void ViewListWidget::setReadWrite( bool rw ) |
395 | { |
396 | foreach ( ViewListItem *c, categories() ) { |
397 | for ( int i = 0; i < c->childCount(); ++i ) { |
398 | static_cast<ViewListItem*>( c->child( i ) )->setReadWrite( rw ); |
399 | } |
400 | } |
401 | } |
402 | |
403 | void ViewListWidget::slotItemChanged( QTreeWidgetItem */*item*/, int /*col */) |
404 | { |
405 | //kDebug(planDbg()); |
406 | } |
407 | |
408 | void ViewListWidget::slotActivated( QTreeWidgetItem *item, QTreeWidgetItem *prev ) |
409 | { |
410 | if ( m_prev ) { |
411 | m_prev->setData( 0, Qt::BackgroundRole, QVariant() ); |
412 | } |
413 | if ( item && item->type() == ViewListItem::ItemType_Category ) { |
414 | return ; |
415 | } |
416 | emit activated( static_cast<ViewListItem*>( item ), static_cast<ViewListItem*>( prev ) ); |
417 | if ( item ) { |
418 | QVariant v = QBrush( QColor( Qt::yellow ) ); |
419 | item->setData( 0, Qt::BackgroundRole, v ); |
420 | m_prev = static_cast<ViewListItem*>( item ); |
421 | } |
422 | } |
423 | |
424 | ViewListItem *ViewListWidget::addCategory( const QString &tag, const QString& name ) |
425 | { |
426 | //kDebug(planDbg()) ; |
427 | ViewListItem *item = m_viewlist->findCategory( tag ); |
428 | if ( item == 0 ) { |
429 | item = new ViewListItem( m_viewlist, tag, QStringList( name ), ViewListItem::ItemType_Category ); |
430 | item->setExpanded( true ); |
431 | item->setFlags( item->flags() | Qt::ItemIsEditable ); |
432 | } |
433 | return item; |
434 | } |
435 | |
436 | QList<ViewListItem*> ViewListWidget::categories() const |
437 | { |
438 | QList<ViewListItem*> lst; |
439 | QTreeWidgetItem *item; |
440 | int cnt = m_viewlist->topLevelItemCount(); |
441 | for ( int i = 0; i < cnt; ++i ) { |
442 | item = m_viewlist->topLevelItem( i ); |
443 | if ( item->type() == ViewListItem::ItemType_Category ) |
444 | lst << static_cast<ViewListItem*>( item ); |
445 | } |
446 | return lst; |
447 | } |
448 | |
449 | ViewListItem *ViewListWidget::findCategory( const QString &tag ) const |
450 | { |
451 | return m_viewlist->findCategory( tag ); |
452 | } |
453 | |
454 | ViewListItem *ViewListWidget::category( const KoView *view ) const |
455 | { |
456 | return m_viewlist->category( view ); |
457 | } |
458 | |
459 | QString ViewListWidget::uniqueTag( const QString &seed ) const |
460 | { |
461 | QString tag = seed; |
462 | for ( int i = 1; findItem( tag ); ++i ) { |
463 | tag = QString("%1-%2" ).arg( seed ).arg( i ); |
464 | } |
465 | return tag; |
466 | } |
467 | |
468 | ViewListItem *ViewListWidget::addView(QTreeWidgetItem *category, const QString &tag, const QString &name, ViewBase *view, KoDocument *doc, const QString &iconName, int index) |
469 | { |
470 | ViewListItem * item = new ViewListItem( uniqueTag( tag ), QStringList( name ), ViewListItem::ItemType_SubView ); |
471 | item->setView( view ); |
472 | item->setDocument( doc ); |
473 | if (! iconName.isEmpty()) { |
474 | item->setData(0, Qt::DecorationRole, KIcon(iconName)); |
475 | } |
476 | item->setFlags( ( item->flags() | Qt::ItemIsEditable ) & ~Qt::ItemIsDropEnabled ); |
477 | insertViewListItem( item, category, index ); |
478 | |
479 | connect(view, SIGNAL(optionsModified()), SLOT(setModified())); |
480 | |
481 | return item; |
482 | } |
483 | |
484 | void ViewListWidget::setSelected( QTreeWidgetItem *item ) |
485 | { |
486 | //kDebug(planDbg())<<item<<","<<m_viewlist->currentItem(); |
487 | if ( item == 0 && m_viewlist->currentItem() ) { |
488 | m_viewlist->currentItem()->setSelected( false ); |
489 | if ( m_prev ) { |
490 | m_prev->setData( 0, Qt::BackgroundRole, QVariant() ); |
491 | } |
492 | } |
493 | m_viewlist->setCurrentItem( item ); |
494 | //kDebug(planDbg())<<item<<","<<m_viewlist->currentItem(); |
495 | } |
496 | |
497 | void ViewListWidget::setCurrentItem( QTreeWidgetItem *item ) |
498 | { |
499 | m_viewlist->setCurrentItem( item ); |
500 | //kDebug(planDbg())<<item<<","<<m_viewlist->currentItem(); |
501 | } |
502 | |
503 | ViewListItem *ViewListWidget::currentItem() const |
504 | { |
505 | return static_cast<ViewListItem*>( m_viewlist->currentItem() ); |
506 | } |
507 | |
508 | ViewListItem *ViewListWidget::currentCategory() const |
509 | { |
510 | ViewListItem *item = static_cast<ViewListItem*>( m_viewlist->currentItem() ); |
511 | if ( item == 0 ) { |
512 | return 0; |
513 | } |
514 | if ( item->type() == ViewListItem::ItemType_Category ) { |
515 | return item; |
516 | } |
517 | return static_cast<ViewListItem*>( item->parent() ); |
518 | } |
519 | |
520 | KoView *ViewListWidget::findView( const QString &tag ) const |
521 | { |
522 | ViewListItem *i = findItem( tag ); |
523 | if ( i == 0 ) { |
524 | return 0; |
525 | } |
526 | return i->view(); |
527 | } |
528 | |
529 | ViewListItem *ViewListWidget::findItem( const QString &tag ) const |
530 | { |
531 | ViewListItem *item = findItem( tag, m_viewlist->invisibleRootItem() ); |
532 | if ( item == 0 ) { |
533 | QTreeWidgetItem *parent = m_viewlist->invisibleRootItem(); |
534 | for (int i = 0; i < parent->childCount(); ++i ) { |
535 | item = findItem( tag, parent->child( i ) ); |
536 | if ( item != 0 ) { |
537 | break; |
538 | } |
539 | } |
540 | } |
541 | return item; |
542 | } |
543 | |
544 | ViewListItem *ViewListWidget::findItem( const QString &tag, QTreeWidgetItem *parent ) const |
545 | { |
546 | if ( parent == 0 ) { |
547 | return findItem( tag, m_viewlist->invisibleRootItem() ); |
548 | } |
549 | for (int i = 0; i < parent->childCount(); ++i ) { |
550 | ViewListItem * ch = static_cast<ViewListItem*>( parent->child( i ) ); |
551 | if ( ch->tag() == tag ) { |
552 | //kDebug(planDbg())<<ch<<","<<view; |
553 | return ch; |
554 | } |
555 | ch = findItem( tag, ch ); |
556 | if ( ch ) { |
557 | return ch; |
558 | } |
559 | } |
560 | return 0; |
561 | } |
562 | |
563 | ViewListItem *ViewListWidget::findItem( const ViewBase *view, QTreeWidgetItem *parent ) const |
564 | { |
565 | if ( parent == 0 ) { |
566 | return findItem( view, m_viewlist->invisibleRootItem() ); |
567 | } |
568 | for (int i = 0; i < parent->childCount(); ++i ) { |
569 | ViewListItem * ch = static_cast<ViewListItem*>( parent->child( i ) ); |
570 | if ( ch->view() == view ) { |
571 | //kDebug(planDbg())<<ch<<","<<view; |
572 | return ch; |
573 | } |
574 | ch = findItem( view, ch ); |
575 | if ( ch ) { |
576 | return ch; |
577 | } |
578 | } |
579 | return 0; |
580 | } |
581 | |
582 | void ViewListWidget::slotAddView() |
583 | { |
584 | emit createView(); |
585 | } |
586 | |
587 | void ViewListWidget::slotRemoveCategory() |
588 | { |
589 | if ( m_contextitem == 0 ) { |
590 | return; |
591 | } |
592 | if ( m_contextitem->type() != ViewListItem::ItemType_Category ) { |
593 | return; |
594 | } |
595 | kDebug(planDbg())<<m_contextitem<<":" <<m_contextitem->type(); |
596 | if ( m_contextitem->childCount() > 0 ) { |
597 | if ( KMessageBox::warningContinueCancel( this, i18n( "Removing this category will also remove all its views." ) ) == KMessageBox::Cancel ) { |
598 | return; |
599 | } |
600 | } |
601 | // first remove all views in this category |
602 | while ( m_contextitem->childCount() > 0 ) { |
603 | ViewListItem *itm = static_cast<ViewListItem*>( m_contextitem->child( 0 ) ); |
604 | takeViewListItem( itm ); |
605 | delete itm->view(); |
606 | delete itm; |
607 | } |
608 | takeViewListItem( m_contextitem ); |
609 | delete m_contextitem; |
610 | m_contextitem = 0; |
611 | emit modified(); |
612 | } |
613 | |
614 | void ViewListWidget::slotRemoveView() |
615 | { |
616 | if ( m_contextitem ) { |
617 | takeViewListItem( m_contextitem ); |
618 | delete m_contextitem->view(); |
619 | delete m_contextitem; |
620 | emit modified(); |
621 | } |
622 | } |
623 | |
624 | void ViewListWidget::slotEditViewTitle() |
625 | { |
626 | //QTreeWidgetItem *item = m_viewlist->currentItem(); |
627 | if ( m_contextitem ) { |
628 | kDebug(planDbg())<<m_contextitem<<":" <<m_contextitem->type(); |
629 | QString title = m_contextitem->text( 0 ); |
630 | m_viewlist->editItem( m_contextitem ); |
631 | if ( title != m_contextitem->text( 0 ) ) { |
632 | emit modified(); |
633 | } |
634 | } |
635 | } |
636 | |
637 | void ViewListWidget::slotConfigureItem() |
638 | { |
639 | if ( m_contextitem == 0 ) { |
640 | return; |
641 | } |
642 | KDialog *dlg = 0; |
643 | if ( m_contextitem->type() == ViewListItem::ItemType_Category ) { |
644 | kDebug(planDbg())<<m_contextitem<<":" <<m_contextitem->type(); |
645 | dlg = new ViewListEditCategoryDialog( *this, m_contextitem, this ); |
646 | } else if ( m_contextitem->type() == ViewListItem::ItemType_SubView ) { |
647 | dlg = new ViewListEditViewDialog( *this, m_contextitem, this ); |
648 | } |
649 | if ( dlg ) { |
650 | connect(dlg, SIGNAL(finished(int)), SLOT(slotDialogFinished(int))); |
651 | dlg->show(); |
652 | dlg->raise(); |
653 | dlg->activateWindow(); |
654 | } |
655 | } |
656 | |
657 | void ViewListWidget::slotDialogFinished( int result ) |
658 | { |
659 | if ( result == QDialog::Accepted ) { |
660 | emit modified(); |
661 | } |
662 | if ( sender() ) { |
663 | sender()->deleteLater(); |
664 | } |
665 | } |
666 | |
667 | void ViewListWidget::slotEditDocumentTitle() |
668 | { |
669 | //QTreeWidgetItem *item = m_viewlist->currentItem(); |
670 | if ( m_contextitem ) { |
671 | kDebug(planDbg())<<m_contextitem<<":" <<m_contextitem->type(); |
672 | QString title = m_contextitem->text( 0 ); |
673 | m_viewlist->editItem( m_contextitem ); |
674 | } |
675 | } |
676 | |
677 | int ViewListWidget::removeViewListItem( ViewListItem *item ) |
678 | { |
679 | QTreeWidgetItem *p = item->parent(); |
680 | if ( p == 0 ) { |
681 | p = m_viewlist->invisibleRootItem(); |
682 | } |
683 | int i = p->indexOfChild( item ); |
684 | if ( i != -1 ) { |
685 | p->takeChild( i ); |
686 | emit modified(); |
687 | } |
688 | return i; |
689 | } |
690 | |
691 | void ViewListWidget::addViewListItem( ViewListItem *item, QTreeWidgetItem *parent, int index ) |
692 | { |
693 | QTreeWidgetItem *p = parent; |
694 | if ( p == 0 ) { |
695 | p = m_viewlist->invisibleRootItem(); |
696 | } |
697 | if ( index == -1 ) { |
698 | index = p->childCount(); |
699 | } |
700 | p->insertChild( index, item ); |
701 | emit modified(); |
702 | } |
703 | |
704 | int ViewListWidget::takeViewListItem( ViewListItem *item ) |
705 | { |
706 | while ( item->childCount() > 0 ) { |
707 | takeViewListItem( static_cast<ViewListItem*>( item->child( 0 ) ) ); |
708 | } |
709 | int pos = removeViewListItem( item ); |
710 | if ( pos != -1 ) { |
711 | emit viewListItemRemoved( item ); |
712 | if ( item == m_prev ) { |
713 | m_prev = 0; |
714 | } |
715 | if ( m_prev ) { |
716 | setCurrentItem( m_prev ); |
717 | } |
718 | } |
719 | return pos; |
720 | } |
721 | |
722 | void ViewListWidget::insertViewListItem( ViewListItem *item, QTreeWidgetItem *parent, int index ) |
723 | { |
724 | addViewListItem( item, parent, index ); |
725 | emit viewListItemInserted( item, static_cast<ViewListItem*>( parent ), index ); |
726 | } |
727 | |
728 | void ViewListWidget::() |
729 | { |
730 | // NOTE: can't use xml file as there may not be a factory() |
731 | QAction *action; |
732 | // view actions |
733 | action = new QAction(koIcon("edit-rename" ), i18nc("@action:inmenu rename view" , "Rename" ), this); |
734 | connect( action, SIGNAL(triggered(bool)), this, SLOT(slotEditViewTitle()) ); |
735 | m_viewactions.append( action ); |
736 | |
737 | action = new QAction(koIcon("configure" ), i18nc("@action:inmenu configure view" , "Configure..." ), this ); |
738 | connect( action, SIGNAL(triggered(bool)), this, SLOT(slotConfigureItem()) ); |
739 | m_viewactions.append( action ); |
740 | |
741 | action = new QAction(koIcon("list-remove" ), i18nc("@action:inmenu remove view" , "Remove" ), this); |
742 | connect( action, SIGNAL(triggered(bool)), this, SLOT(slotRemoveView()) ); |
743 | m_viewactions.append( action ); |
744 | |
745 | action = new QAction( this ); |
746 | action->setSeparator( true ); |
747 | m_viewactions.append( action ); |
748 | |
749 | // Category actions |
750 | action = new QAction(koIcon("edit-rename" ), i18nc("@action:inmenu rename view category" , "Rename" ), this); |
751 | connect( action, SIGNAL(triggered(bool)), SLOT(renameCategory()) ); |
752 | m_categoryactions.append( action ); |
753 | |
754 | action = new QAction(koIcon("configure" ), i18nc("@action:inmenu configure view category" , "Configure..." ), this); |
755 | connect( action, SIGNAL(triggered(bool)), this, SLOT(slotConfigureItem()) ); |
756 | m_categoryactions.append( action ); |
757 | |
758 | action = new QAction(koIcon("list-remove" ), i18nc("@action:inmenu Remove view category" , "Remove" ),this); |
759 | connect( action, SIGNAL(triggered(bool)), this, SLOT(slotRemoveCategory()) ); |
760 | m_categoryactions.append( action ); |
761 | |
762 | action = new QAction( this ); |
763 | action->setSeparator( true ); |
764 | m_categoryactions.append( action ); |
765 | |
766 | // list actions |
767 | action = new QAction(koIcon("list-add" ), i18nc("@action:inmenu Insert View" , "Insert..." ), this); |
768 | connect( action, SIGNAL(triggered(bool)), this, SLOT(slotAddView()) ); |
769 | m_listactions.append( action ); |
770 | } |
771 | |
772 | void ViewListWidget::renameCategory() |
773 | { |
774 | if ( m_contextitem ) { |
775 | QString title = m_contextitem->text( 0 ); |
776 | m_viewlist->editItem( m_contextitem, 0 ); |
777 | } |
778 | } |
779 | |
780 | void ViewListWidget:: ( QContextMenuEvent *event ) |
781 | { |
782 | KMenu ; |
783 | QList<QAction*> lst; |
784 | m_contextitem = static_cast<ViewListItem*>(m_viewlist->itemAt( event->pos() ) ); |
785 | if ( m_contextitem == 0 ) { |
786 | lst += m_listactions; |
787 | } else { |
788 | if ( m_contextitem->type() == ViewListItem::ItemType_Category ) { |
789 | lst += m_categoryactions; |
790 | } else if ( m_contextitem->type() == ViewListItem::ItemType_SubView ) { |
791 | lst += m_viewactions; |
792 | ViewBase *v = dynamic_cast<ViewBase*>( m_contextitem->view() ); |
793 | if ( v ) { |
794 | lst += v->viewlistActionList(); |
795 | } |
796 | } |
797 | lst += m_listactions; |
798 | } |
799 | if ( ! lst.isEmpty() ) { |
800 | //menu.addTitle( i18n( "Edit" ) ); |
801 | foreach ( QAction *a, lst ) { |
802 | menu.addAction( a ); |
803 | } |
804 | } |
805 | if ( ! menu.actions().isEmpty() ) { |
806 | menu.exec( event->globalPos() ); |
807 | } |
808 | } |
809 | |
810 | void ViewListWidget::save( QDomElement &element ) const |
811 | { |
812 | m_viewlist->save( element ); |
813 | } |
814 | |
815 | void ViewListWidget::setProject( Project *project ) |
816 | { |
817 | kDebug(planDbg())<<project; |
818 | m_model.setProject( project ); |
819 | } |
820 | |
821 | void ViewListWidget::slotCurrentScheduleChanged( int idx ) |
822 | { |
823 | kDebug(planDbg())<<idx<<selectedSchedule(); |
824 | emit selectionChanged( selectedSchedule() ); |
825 | } |
826 | |
827 | ScheduleManager *ViewListWidget::selectedSchedule() const |
828 | { |
829 | QModelIndex idx = m_sfModel.index( m_currentSchedule->currentIndex(), m_currentSchedule->modelColumn() ); |
830 | kDebug(planDbg())<<idx; |
831 | return m_sfModel.manager( idx ); |
832 | } |
833 | |
834 | void ViewListWidget::setSelectedSchedule( ScheduleManager *sm ) |
835 | { |
836 | kDebug(planDbg())<<sm<<m_model.index( sm ); |
837 | QModelIndex idx = m_sfModel.mapFromSource( m_model.index( sm ) ); |
838 | if ( sm && ! idx.isValid()) { |
839 | m_temp = sm; |
840 | return; |
841 | } |
842 | m_currentSchedule->setCurrentIndex( idx.row() ); |
843 | kDebug(planDbg())<<sm<<idx; |
844 | m_temp = 0; |
845 | } |
846 | |
847 | void ViewListWidget::slotScheduleManagerAdded( ScheduleManager *sm ) |
848 | { |
849 | if ( m_temp && m_temp == sm ) { |
850 | setSelectedSchedule( sm ); |
851 | m_temp = 0; |
852 | } |
853 | } |
854 | |
855 | void ViewListWidget::setModified() |
856 | { |
857 | emit modified(); |
858 | } |
859 | |
860 | } //KPlato namespace |
861 | |
862 | #include "kptviewlist.moc" |
863 | |