1/* This file is part of the KDE project
2 Copyright (C) 2007, 2012 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 "kptdocumentmodel.h"
21
22#include "kptdocuments.h"
23#include "kptglobal.h"
24#include "kptcommonstrings.h"
25#include "kptdebug.h"
26
27#include <QMimeData>
28
29
30class KoDocument;
31
32namespace KPlato
33{
34
35QVariant DocumentModel::url( const Document *doc, int role ) const
36{
37 switch ( role ) {
38 case Qt::DisplayRole:
39 case Qt::EditRole:
40 case Qt::ToolTipRole:
41 return doc->url().url();
42 case Qt::StatusTipRole:
43 case Qt::WhatsThisRole:
44 return QVariant();
45 }
46 return QVariant();
47}
48
49QVariant DocumentModel::name( const Document *doc, int role ) const
50{
51 switch ( role ) {
52 case Qt::DisplayRole:
53 case Qt::EditRole:
54 case Qt::ToolTipRole:
55 return doc->name();
56 case Qt::StatusTipRole:
57 case Qt::WhatsThisRole:
58 return QVariant();
59 }
60 return QVariant();
61}
62
63bool DocumentModel::setName( Document *doc, const QVariant &value, int role )
64{
65 switch ( role ) {
66 case Qt::EditRole:
67 doc->setName( value.toString() );
68 return true;
69 default:
70 break;
71 }
72 return false;
73}
74
75QVariant DocumentModel::type( const Document *doc, int role ) const
76{
77 switch ( role ) {
78 case Qt::DisplayRole:
79 case Qt::ToolTipRole:
80 return Document::typeToString( doc->type(), true );
81 case Role::EnumList:
82 return Document::typeList( true );
83 case Qt::EditRole:
84 case Role::EnumListValue:
85 return (int)doc->type();
86 case Qt::TextAlignmentRole:
87 return Qt::AlignCenter;
88 case Qt::StatusTipRole:
89 case Qt::WhatsThisRole:
90 return QVariant();
91 default:
92 break;
93 }
94 return QVariant();
95}
96
97bool DocumentModel::setType( Document *doc, const QVariant &value, int role )
98{
99 switch ( role ) {
100 case Qt::EditRole:
101 doc->setType( static_cast<Document::Type>( value.toInt() ) );
102 return true;
103 default:
104 break;
105 }
106 return false;
107}
108
109QVariant DocumentModel::status( const Document *doc, int role ) const
110{
111 switch ( role ) {
112 case Qt::DisplayRole:
113 case Qt::EditRole:
114 case Qt::ToolTipRole: {
115 return doc->status();
116 }
117 case Qt::StatusTipRole:
118 case Qt::WhatsThisRole:
119 return QVariant();
120 }
121 return QVariant();
122}
123
124QVariant DocumentModel::sendAs( const Document *doc, int role ) const
125{
126 switch ( role ) {
127 case Qt::DisplayRole:
128 case Qt::ToolTipRole:
129 return Document::sendAsToString( doc->sendAs(), true );
130 case Role::EnumList:
131 return Document::sendAsList( true );
132 case Qt::EditRole:
133 case Role::EnumListValue:
134 return (int)doc->sendAs();
135 case Qt::TextAlignmentRole:
136 return Qt::AlignCenter;
137 case Qt::StatusTipRole:
138 case Qt::WhatsThisRole:
139 return QVariant();
140 default:
141 break;
142 }
143 return QVariant();
144}
145
146bool DocumentModel::setSendAs( Document *doc, const QVariant &value, int role )
147{
148 switch ( role ) {
149 case Qt::EditRole:
150 doc->setSendAs( static_cast<Document::SendAs>( value.toInt() ) );
151 return true;
152 default:
153 break;
154 }
155 return false;
156}
157
158QVariant DocumentModel::data( const Document *doc, int property, int role ) const
159{
160 QVariant result;
161 switch ( property ) {
162 case Property_Url: result = url( doc, role ); break;
163 case Property_Name: result = name( doc, role ); break;
164 case Property_Type: result = type( doc, role ); break;
165 case Property_SendAs: result = sendAs( doc, role ); break;
166 case Property_Status: result = status( doc, role ); break;
167 default:
168 //kDebug(planDbg())<<"Invalid property number: "<<property;
169 return result;
170 }
171 return result;
172}
173
174int DocumentModel::propertyCount()
175{
176 return 5;
177}
178
179bool DocumentModel::setData( Document *doc, int property, const QVariant & /*value*/, int role )
180{
181 Q_UNUSED(doc);
182 Q_UNUSED(property);
183 Q_UNUSED(role);
184 switch ( property ) {
185 //case 0: result = url( doc, role ); break;
186 //case 1: return setType( doc, value, role );
187 //case 2: result = status( doc, role ); break;
188 default:
189 //kDebug(planDbg())<<"Invalid property number: "<<property;
190 break;
191 }
192 return false;
193}
194
195QVariant DocumentModel::headerData( int section, int role )
196{
197 if ( role == Qt::DisplayRole ) {
198 switch ( section ) {
199 case Property_Url: return i18n( "Url" );
200 case Property_Name: return i18n( "Name" );
201 case Property_Type: return i18n( "Type" );
202 case Property_SendAs: return i18n( "Send As" );
203 case Property_Status: return i18n( "Status" );
204
205 default: return QVariant();
206 }
207 }
208 if ( role == Qt::ToolTipRole ) {
209 switch ( section ) {
210 case Property_Url: return ToolTip::documentUrl();
211 case Property_Name: return QVariant(); //TODO
212 case Property_Type: return ToolTip::documentType();
213 case Property_SendAs: return ToolTip::documentSendAs();
214 case Property_Status: return ToolTip::documentStatus();
215
216 default: return QVariant();
217 }
218 }
219 return QVariant();
220}
221
222//----------------------------
223DocumentItemModel::DocumentItemModel( QObject *parent )
224 : ItemModelBase( parent ),
225 m_documents( 0 )
226{
227}
228
229DocumentItemModel::~DocumentItemModel()
230{
231}
232
233void DocumentItemModel::slotDocumentToBeInserted( Documents *parent, int row )
234{
235 if ( parent == m_documents ) {
236 beginInsertRows( QModelIndex(), row, row );
237 }
238}
239
240void DocumentItemModel::slotDocumentInserted( Document *doc )
241{
242 if ( m_documents->contains( doc ) ) {
243 endInsertRows();
244 }
245}
246
247void DocumentItemModel::slotDocumentToBeRemoved( Document *doc )
248{
249 if ( m_documents->contains( doc ) ) {
250 int row = m_documents->indexOf( doc );
251 beginRemoveRows( QModelIndex(), row, row );
252 }
253}
254
255void DocumentItemModel::slotDocumentRemoved( Document *doc )
256{
257 Q_UNUSED(doc);
258 //FIXME
259 endRemoveRows();
260}
261
262void DocumentItemModel::setDocuments( Documents *docs )
263{
264 //kDebug(planDbg())<<m_documents<<docs;
265 if ( m_documents ) {
266 }
267 m_documents = docs;
268 if ( m_documents ) {
269 }
270 reset();
271}
272
273Documents *DocumentItemModel::documents() const
274{
275 return m_documents;
276}
277
278Qt::ItemFlags DocumentItemModel::flags( const QModelIndex &index ) const
279{
280 Qt::ItemFlags flags = QAbstractItemModel::flags( index );
281 if ( !index.isValid() ) {
282 if ( m_readWrite ) {
283 flags |= Qt::ItemIsDropEnabled;
284 }
285 return flags;
286 }
287 //kDebug(planDbg())<<index<<m_readWrite;
288 if ( m_readWrite ) {
289 flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
290 switch ( index.column() ) {
291 case DocumentModel::Property_Url: // url
292 flags &= ~Qt::ItemIsEditable; // wee need a full path
293 break;
294 case DocumentModel::Property_Name: // name
295 flags |= Qt::ItemIsEditable;
296 break;
297 case DocumentModel::Property_Type: // type
298 flags |= Qt::ItemIsEditable;
299 break;
300 case DocumentModel::Property_SendAs: // sendAs
301 flags |= Qt::ItemIsEditable;
302 break;
303 case DocumentModel::Property_Status: // status
304 flags &= ~Qt::ItemIsEditable;
305 break;
306 default:
307 flags &= ~Qt::ItemIsEditable;
308 }
309 }
310 return flags;
311}
312
313QModelIndex DocumentItemModel::parent( const QModelIndex &/*index*/ ) const
314{
315 return QModelIndex();
316}
317
318QModelIndex DocumentItemModel::index( int row, int column, const QModelIndex &parent ) const
319{
320 if ( parent.isValid() ) {
321 return QModelIndex();
322 }
323 if ( m_documents == 0 || column < 0 || column >= columnCount() || row < 0 ) {
324 //kDebug(planDbg())<<"No index for"<<row<<","<<column;
325 return QModelIndex();
326 }
327 if ( row >= m_documents->count() ) {
328 return QModelIndex();
329 }
330 return createIndex(row, column );
331}
332
333QModelIndex DocumentItemModel::index( const Document *doc ) const
334{
335 if ( m_documents == 0 || ! doc->isValid() ) {
336 return QModelIndex();
337 }
338 if ( ! m_documents->contains( doc ) ) {
339 return QModelIndex();
340 }
341 return createIndex( m_documents->indexOf( doc ), 0 );
342}
343
344bool DocumentItemModel::setUrl( Document *doc, const QVariant &value, int role )
345{
346 switch ( role ) {
347 case Qt::EditRole:
348 if ( KUrl( value.toString() ) == doc->url() ) {
349 return false;
350 }
351 //m_part->addCommand( new DocumentModifyUrlCmd( *doc, value.toString(), "Modify Document Url" ) );
352 return true;
353 }
354 return false;
355}
356
357bool DocumentItemModel::setName( Document *doc, const QVariant &value, int role )
358{
359 switch ( role ) {
360 case Qt::EditRole:
361 //m_part->addCommand( new DocumentModifyTypeCmd( *doc, value.toString(), "Modify Document Type" ) );
362 return m_model.setName( doc, value, role );
363 }
364 return false;
365}
366
367bool DocumentItemModel::setType( Document *doc, const QVariant &value, int role )
368{
369 switch ( role ) {
370 case Qt::EditRole:
371 if ( value.toInt() == doc->type() ) {
372 return false;
373 }
374 m_model.setType( doc, value, role );
375 //m_part->addCommand( new DocumentModifyTypeCmd( *doc, value.toString(), "Modify Document Type" ) );
376 return true;
377 }
378 return false;
379}
380
381bool DocumentItemModel::setSendAs( Document *doc, const QVariant &value, int role )
382{
383 switch ( role ) {
384 case Qt::EditRole:
385 if ( value.toInt() == doc->sendAs() ) {
386 return false;
387 }
388 m_model.setSendAs( doc, value, role );
389 //m_part->addCommand( new DocumentModifyTypeCmd( *doc, value.toString(), "Modify Document Type" ) );
390 return true;
391 }
392 return false;
393}
394
395
396QVariant DocumentItemModel::data( const QModelIndex &index, int role ) const
397{
398 QVariant result;
399 const Document *doc = document( index );
400 if ( doc ) {
401 result = m_model.data( doc, index.column(), role );
402 }
403 if ( result.isValid() ) {
404 if ( role == Qt::DisplayRole && result.type() == QVariant::String && result.toString().isEmpty()) {
405 // HACK to show focus in empty cells
406 result = ' ';
407 }
408 return result;
409 }
410 return result;
411}
412
413bool DocumentItemModel::setData( const QModelIndex &index, const QVariant &value, int role )
414{
415 if ( ! index.isValid() ) {
416 return ItemModelBase::setData( index, value, role );
417 }
418 if ( ( flags(index) & Qt::ItemIsEditable ) == 0 || role != Qt::EditRole ) {
419 return false;
420 }
421 bool result = false;
422 Document *doc = document( index );
423 switch (index.column()) {
424 case DocumentModel::Property_Url:
425 result = setUrl( doc, value, role );
426 break;
427 case DocumentModel::Property_Name:
428 result = setName( doc, value, role );
429 break;
430 case DocumentModel::Property_Type:
431 result = setType( doc, value, role );
432 break;
433 case DocumentModel::Property_SendAs:
434 result = setSendAs( doc, value, role );
435 break;
436 default:
437 qWarning("data: invalid display value column %d", index.column());
438 break;
439 }
440 if ( result ) {
441 emit dataChanged( index, index );
442 }
443 return result;
444}
445
446QVariant DocumentItemModel::headerData( int section, Qt::Orientation orientation, int role ) const
447{
448 if ( orientation == Qt::Horizontal ) {
449 if ( role == Qt::DisplayRole ) {
450 return m_model.headerData( section, role );
451 } else if ( role == Qt::TextAlignmentRole ) {
452 switch (section) {
453 case DocumentModel::Property_Type: return Qt::AlignCenter;
454 case DocumentModel::Property_SendAs: return Qt::AlignCenter;
455 default: return QVariant();
456 }
457 }
458 }
459 if ( role == Qt::ToolTipRole ) {
460 return DocumentModel::headerData( section, role );
461 }
462 return ItemModelBase::headerData(section, orientation, role);
463}
464
465QAbstractItemDelegate *DocumentItemModel::createDelegate( int column, QWidget *parent ) const
466{
467 switch ( column ) {
468 //case 0: return new KUrlDelegate( parent ); //???????
469 case DocumentModel::Property_Type: { kDebug(planDbg())<< column; return new EnumDelegate( parent ); }
470 case DocumentModel::Property_SendAs: { kDebug(planDbg())<< column; return new EnumDelegate( parent ); }
471 default: break;
472 }
473 return 0;
474}
475
476int DocumentItemModel::columnCount( const QModelIndex &/*parent*/ ) const
477{
478 //kDebug(planDbg())<<m_model.propertyCount();
479 return m_model.propertyCount();
480}
481
482int DocumentItemModel::rowCount( const QModelIndex &parent ) const
483{
484 if ( m_documents == 0 || parent.isValid() ) {
485 //kDebug(planDbg())<<parent;
486 return 0;
487 }
488 //kDebug(planDbg())<<parent<<": "<<m_documents->count();
489 return m_documents->count();
490}
491
492Qt::DropActions DocumentItemModel::supportedDropActions() const
493{
494 return Qt::CopyAction | Qt::MoveAction;
495}
496
497
498QStringList DocumentItemModel::mimeTypes() const
499{
500 return QStringList() << "application/x-vnd.kde.plan.documentitemmodel.internal";
501}
502
503QMimeData *DocumentItemModel::mimeData( const QModelIndexList & indexes ) const
504{
505 QMimeData *m = new QMimeData();
506 QByteArray encodedData;
507 //QDataStream stream(&encodedData, QIODevice::WriteOnly);
508 //QList<int> rows;
509 foreach (const QModelIndex &index, indexes) {
510 Q_UNUSED(index);
511 m->setData("application/x-vnd.kde.plan.documentitemmodel.internal", encodedData);
512 }
513 return m;
514}
515
516bool DocumentItemModel::dropAllowed( const QModelIndex &index, int dropIndicatorPosition, const QMimeData *data )
517{
518 Q_UNUSED(index);
519 Q_UNUSED(dropIndicatorPosition);
520 Q_UNUSED(data);
521 //kDebug(planDbg());
522 return true;
523}
524
525bool DocumentItemModel::dropAllowed( Document *on, const QMimeData *data )
526{
527 Q_UNUSED(on)
528 if ( !data->hasFormat("application/x-vnd.kde.plan.documentitemmodel.internal") ) {
529 return false;
530 }
531 return true;
532}
533
534bool DocumentItemModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int /*column*/, const QModelIndex &parent )
535{
536 Q_UNUSED(row);
537 Q_UNUSED(parent);
538 //kDebug(planDbg())<<action;
539 if (action == Qt::IgnoreAction) {
540 return true;
541 }
542 if ( !data->hasFormat( "application/x-vnd.kde.plan.documentitemmodel.internal" ) ) {
543 return false;
544 }
545 return false;
546}
547
548Document *DocumentItemModel::document( const QModelIndex &index ) const
549{
550 if ( m_documents == 0 ) {
551 return 0;
552 }
553 return m_documents->value( index.row() );
554}
555
556void DocumentItemModel::slotDocumentChanged( Document *doc )
557{
558 if ( m_documents == 0 ) {
559 return;
560 }
561 int row = m_documents->indexOf( doc );
562 if ( row == -1 ) {
563 return;
564 }
565 emit dataChanged( createIndex( row, 0 ), createIndex( row, columnCount() - 1 ) );
566}
567
568QModelIndex DocumentItemModel::insertDocument( Document *doc, Document *after )
569{
570 Q_UNUSED(after);
571// m_part->addCommand( new DocumentAddCmd( doc, after, kundo2_i18n( "Add Document") ) );
572 int row = m_documents->indexOf( doc );
573 if ( row == -1 ) {
574 return QModelIndex();
575 }
576 return createIndex( row, 0 );
577}
578
579} //namespace KPlato
580
581#include "kptdocumentmodel.moc"
582