00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <QApplication>
00026 #include <QDebug>
00027 #include <QImage>
00028 #include <QString>
00029 #include <QDataStream>
00030 #include <QMessageBox>
00031 #include <QAbstractItemModel>
00032 #include <QModelIndex>
00033 #include <QPainter>
00034 #include <QStyle>
00035 #include <QVBoxLayout>
00036 #include <QStackedWidget>
00037 #include <QComboBox>
00038 #include <QHeaderView>
00039 #include <QTextDocument>
00040 #include <QTextCursor>
00041 #include <QTextCharFormat>
00042 #include <QListView>
00043 #include <QMenu>
00044 #include <QAction>
00045 #include <QEvent>
00046 #include <QDropEvent>
00047 #include <QDragEnterEvent>
00048 #include <QDragMoveEvent>
00049 #include <QStandardItemModel>
00050 #include <QItemDelegate>
00051 #include <QShortcut>
00052
00053 #include <ui_klflibopenresourcedlg.h>
00054 #include <ui_klflibrespropeditor.h>
00055 #include <ui_klflibnewsubresdlg.h>
00056
00057 #include <klfguiutil.h>
00058 #include "klfconfig.h"
00059 #include "klflibview.h"
00060
00061 #include "klflibview_p.h"
00062
00063
00064
00065
00066
00068 static QImage transparentify_image(const QImage& img, qreal factor)
00069 {
00070
00071 QImage img2 = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
00072 int k, j;
00073 for (k = 0; k < img.height(); ++k) {
00074 for (j = 0; j < img.width(); ++j) {
00075 QRgb c = img2.pixel(j, k);
00076 img2.setPixel(j, k, qRgba(qRed(c),qGreen(c),qBlue(c),(int)(factor*qAlpha(c))));
00077 }
00078 }
00079 return img2;
00080 }
00081
00082
00084 static QImage autocrop_image(const QImage& img, int alpha_threshold = 0)
00085 {
00086
00087 int x, y;
00088 int min_x = -1, max_x = -1, min_y = -1, max_y = -1;
00089
00090 for (x = 0; x < img.width(); ++x) {
00091 for (y = 0; y < img.height(); ++y) {
00092 if (qAlpha(img.pixel(x,y)) - alpha_threshold > 0) {
00093
00094 if (min_x == -1 || min_x > x) min_x = x;
00095 if (max_x == -1 || max_x < x) max_x = x;
00096 if (min_y == -1 || min_y > y) min_y = y;
00097 if (max_y == -1 || max_y < y) max_y = y;
00098 }
00099 }
00100 }
00101 return img.copy(QRect(QPoint(min_x, min_y), QPoint(max_x, max_y)));
00102 }
00103
00105 static float color_distinguishable_distance(QRgb a, QRgb b, bool aPremultiplied = false) {
00106 static const float C_r = 11.f, C_g = 16.f, C_b = 5.f;
00107 static const float C_avg = (C_r + C_g + C_b) / 3.f;
00108
00109
00110
00111
00112
00113
00114
00115 static const float drkfactor = 1;
00116
00117 float alpha = qAlpha(a)/255.f;
00118 QRgb m;
00119 if (aPremultiplied)
00120 m = qRgb((int)(qRed(a)+(1-alpha)*qRed(b)),
00121 (int)(qGreen(a)+(1-alpha)*qGreen(b)),
00122 (int)(qBlue(a)+(1-alpha)*qBlue(b)));
00123 else
00124 m = qRgb((int)(alpha*qRed(a)+(1-alpha)*qRed(b)),
00125 (int)(alpha*qGreen(a)+(1-alpha)*qGreen(b)),
00126 (int)(alpha*qBlue(a)+(1-alpha)*qBlue(b)));
00127
00128 float dst = qMax( qMax(C_r*abs(qRed(m) - qRed(b)), C_g*abs(qGreen(m) - qGreen(b))),
00129 C_b*abs(qBlue(m) - qBlue(b)) ) * drkfactor / C_avg;
00130
00131
00132 return dst;
00133 }
00134
00135
00137 static bool image_is_distinguishable(const QImage& imgsrc, QColor background, float threshold)
00138 {
00139 int fmt = imgsrc.format();
00140 bool apremultiplied;
00141 QImage img;
00142 switch (fmt) {
00143 case QImage::Format_ARGB32: img = imgsrc; apremultiplied = false; break;
00144 case QImage::Format_ARGB32_Premultiplied: img = imgsrc; apremultiplied = true; break;
00145 default:
00146 img = imgsrc.convertToFormat(QImage::Format_ARGB32);
00147 apremultiplied = false;
00148 break;
00149 }
00150 QRgb bg = background.rgb();
00151
00152 int x, y;
00153 for (x = 0; x < img.width(); ++x) {
00154 for (y = 0; y < img.height(); ++y) {
00155
00156
00157 float dist = color_distinguishable_distance(img.pixel(x,y), bg, apremultiplied);
00158 if (dist > threshold) {
00159
00160 return true;
00161 }
00162 }
00163 }
00164 return false;
00165 }
00166
00167
00168
00169
00170
00171 KLFAbstractLibView::KLFAbstractLibView(QWidget *parent)
00172 : QWidget(parent), pResourceEngine(NULL)
00173 {
00174 }
00175
00176 void KLFAbstractLibView::setResourceEngine(KLFLibResourceEngine *resource)
00177 {
00178 if (pResourceEngine)
00179 disconnect(pResourceEngine, 0, this, 0);
00180 pResourceEngine = resource;
00181 connect(pResourceEngine, SIGNAL(dataChanged(const QString&, int, const QList<KLFLib::entryId>&)),
00182 this, SLOT(updateResourceData(const QString&, int, const QList<KLFLib::entryId>&)));
00183 connect(pResourceEngine, SIGNAL(resourcePropertyChanged(int)),
00184 this, SLOT(updateResourceProp(int)));
00185 connect(pResourceEngine, SIGNAL(defaultSubResourceChanged(const QString&)),
00186 this, SLOT(updateResourceDefaultSubResourceChanged(const QString&)));
00187 updateResourceEngine();
00188 }
00189
00190 void KLFAbstractLibView::updateResourceDefaultSubResourceChanged(const QString& )
00191 {
00192 updateResourceEngine();
00193 }
00194
00195 void KLFAbstractLibView::wantMoreCategorySuggestions()
00196 {
00197 emit moreCategorySuggestions(getCategorySuggestions());
00198 }
00199
00200 QList<QAction*> KLFAbstractLibView::addContextMenuActions(const QPoint&)
00201 {
00202 return QList<QAction*>();
00203 }
00204
00205
00206
00207
00208
00209 QList<KLFLibViewFactory*> KLFLibViewFactory::pRegisteredFactories =
00210 QList<KLFLibViewFactory*>();
00211
00212
00213 KLFLibViewFactory::KLFLibViewFactory(const QStringList& viewTypeIdentifiers,
00214 QObject *parent)
00215 : QObject(parent), pViewTypeIdentifiers(viewTypeIdentifiers)
00216 {
00217 registerFactory(this);
00218 }
00219 KLFLibViewFactory::~KLFLibViewFactory()
00220 {
00221 unRegisterFactory(this);
00222 }
00223
00224
00225 QString KLFLibViewFactory::defaultViewTypeIdentifier()
00226 {
00227 if (pRegisteredFactories.size() > 0)
00228 return pRegisteredFactories[0]->pViewTypeIdentifiers.first();
00229 return QString();
00230 }
00231
00232 KLFLibViewFactory *KLFLibViewFactory::findFactoryFor(const QString& viewTypeIdentifier)
00233 {
00234 if (viewTypeIdentifier.isEmpty()) {
00235 if (pRegisteredFactories.size() > 0)
00236 return pRegisteredFactories[0];
00237 return NULL;
00238 }
00239 int k;
00240
00241 for (k = 0; k < pRegisteredFactories.size(); ++k) {
00242 if (pRegisteredFactories[k]->viewTypeIdentifiers().contains(viewTypeIdentifier))
00243 return pRegisteredFactories[k];
00244 }
00245
00246 return NULL;
00247 }
00248
00249 QStringList KLFLibViewFactory::allSupportedViewTypeIdentifiers()
00250 {
00251 QStringList list;
00252 int k;
00253 for (k = 0; k < pRegisteredFactories.size(); ++k)
00254 list << pRegisteredFactories[k]->viewTypeIdentifiers();
00255 return list;
00256 }
00257
00258
00259 void KLFLibViewFactory::registerFactory(KLFLibViewFactory *factory)
00260 {
00261 KLF_ASSERT_NOT_NULL( factory, "Attempt to register NULL factory!", return )
00262 ;
00263
00264 if (factory->pViewTypeIdentifiers.size() == 0) {
00265 qWarning("KLFLibViewFactory::registerFactory: factory must provide at least one view type!");
00266 return;
00267 }
00268 if (pRegisteredFactories.indexOf(factory) != -1)
00269 return;
00270 pRegisteredFactories.append(factory);
00271 }
00272
00273 void KLFLibViewFactory::unRegisterFactory(KLFLibViewFactory *factory)
00274 {
00275 if (pRegisteredFactories.indexOf(factory) == -1)
00276 return;
00277 pRegisteredFactories.removeAll(factory);
00278 }
00279
00280
00281
00282
00283
00284
00285
00286 KLFFactoryManager KLFLibWidgetFactory::pFactoryManager;
00287
00288 KLFLibWidgetFactory::KLFLibWidgetFactory(QObject *parent)
00289 : QObject(parent), KLFFactoryBase(&pFactoryManager)
00290 {
00291 }
00292
00293
00294 KLFLibWidgetFactory *KLFLibWidgetFactory::findFactoryFor(const QString& wtype)
00295 {
00296 return dynamic_cast<KLFLibWidgetFactory*>(pFactoryManager.findFactoryFor(wtype));
00297 }
00298
00299
00300 QStringList KLFLibWidgetFactory::allSupportedWTypes()
00301 {
00302 return pFactoryManager.allSupportedTypes();
00303 }
00304
00305
00306 bool KLFLibWidgetFactory::hasCreateWidget(const QString& ) const
00307 {
00308 return false;
00309 }
00310
00311 QWidget * KLFLibWidgetFactory::createPromptCreateParametersWidget(QWidget *,
00312 const QString& ,
00313 const Parameters& )
00314 {
00315 return NULL;
00316 }
00317 KLFLibWidgetFactory::Parameters
00318 KLFLibWidgetFactory::retrieveCreateParametersFromWidget(const QString& ,
00319 QWidget *)
00320 {
00321 return Parameters();
00322 }
00323
00324 bool KLFLibWidgetFactory::hasSaveToWidget(const QString& ) const
00325 {
00326 return false;
00327 }
00328 QWidget *KLFLibWidgetFactory::createPromptSaveToWidget(QWidget *,
00329 const QString& ,
00330 KLFLibResourceEngine* ,
00331 const QUrl& )
00332 {
00333 return NULL;
00334 }
00335 QUrl KLFLibWidgetFactory::retrieveSaveToUrlFromWidget(const QString& ,
00336 QWidget *)
00337 {
00338 return QUrl();
00339 }
00340
00341
00342
00343
00344
00345
00346 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibModelCache::NodeId& n)
00347 {
00348 const char * skind =
00349 ( (n.kind == KLFLibModelCache::EntryKind) ? "EntryKind" :
00350 ((n.kind == KLFLibModelCache::CategoryLabelKind) ? "CategoryLabelKind" :
00351 "*UnknownKind*") );
00352 return dbg.nospace() << "NodeId("<<skind<<"+"<<n.index<<")";
00353 }
00354 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibModelCache::Node& n)
00355 {
00356 return dbg << "[kind="<<n.kind<<", children/sz="<<n.children.size()
00357 <<",allfetched="<<n.allChildrenFetched<<"]";
00358 }
00359 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibModelCache::EntryNode& en)
00360 {
00361 return dbg << "EntryNode(entryid="<<en.entryid<<"; entry/latex="<<en.entry.latex()<<"; parent="
00362 <<en.parent<<")";
00363 }
00364 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibModelCache::CategoryLabelNode& cn)
00365 {
00366 return dbg << "CategoryLabelNode(label="<<cn.categoryLabel<<";fullCategoryPath="<<cn.fullCategoryPath
00367 << "; parent="<<cn.parent<<";"<<(const KLFLibModelCache::Node&)cn<<")";
00368 }
00369 KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibModel::PersistentId& n)
00370 {
00371 return dbg << "PersistentId("<<n.kind<<", entry_id="<<n.entry_id<<", cat...path="<<n.categorylabel_fullpath<<")";
00372 }
00373 KLF_EXPORT QDebug& operator<<(QDebug& d, const KLFLibViewDelegate::ColorRegion& c)
00374 {
00375 return d << "ColorRegion["<<c.start<<"->+"<<c.len<<"]";
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 bool KLFLibModelCache::KLFLibModelSorter::operator()(const NodeId& a, const NodeId& b)
00388 {
00389 if ( ! a.valid() || ! b.valid() )
00390 return false;
00391
00392 if ( groupCategories ) {
00393
00394 if ( a.kind != EntryKind && b.kind == EntryKind ) {
00395 return true;
00396 } else if ( a.kind == EntryKind && b.kind != EntryKind ) {
00397 return false;
00398 }
00399 if ( a.kind != EntryKind && b.kind != EntryKind ) {
00400 if ( ! (a.kind == CategoryLabelKind && b.kind == CategoryLabelKind) ) {
00401 qWarning("KLFLibModelSorter::operator(): Bad node kinds!! a: %d and b: %d",
00402 a.kind, b.kind);
00403 return false;
00404 }
00405
00406 return QString::localeAwareCompare(cache->getCategoryLabelNodeRef(a).categoryLabel,
00407 cache->getCategoryLabelNodeRef(b).categoryLabel) < 0;
00408 }
00409
00410 return entrysorter->operator()(cache->getEntryNodeRef(a).entry, cache->getEntryNodeRef(b).entry);
00411 }
00412
00413 int entryProp = entrysorter->propId();
00414 int sortorderfactor = (entrysorter->order() == Qt::AscendingOrder) ? 1 : -1;
00415 QString nodevaluea = cache->nodeValue(a, entryProp);
00416 QString nodevalueb = cache->nodeValue(b, entryProp);
00417 return sortorderfactor*QString::localeAwareCompare(nodevaluea, nodevalueb) < 0;
00418 }
00419
00420
00421
00422
00423
00424 void KLFLibModelCache::rebuildCache()
00425 {
00426 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00427 klfDbg(klfFmtCC("flavorFlags=%#010x", pModel->pFlavorFlags));
00428 int k;
00429
00430
00431 #ifndef Q_WS_MAC
00432 KLFProgressReporter progressReporter(0, 100, NULL);
00433 QString msg = QObject::tr("Updating View...", "[[KLFLibModelCache, progress text]]");
00434 emit pModel->operationStartReportingProgress(&progressReporter, msg);
00435 progressReporter.doReportProgress(0);
00436 #endif
00437
00438 klfDbgT("saving persistent indexes ...");
00439 QModelIndexList persistentIndexes = pModel->persistentIndexList();
00440 QList<KLFLibModel::PersistentId> persistentIndexIds = pModel->persistentIdList(persistentIndexes);
00441 klfDbgT("... done saving persistent indexes.");
00442
00443
00444 pEntryCache.clear();
00445 pCategoryLabelCache.clear();
00446
00447 pCategoryLabelCache.append(CategoryLabelNode());
00448 CategoryLabelNode& root = pCategoryLabelCache[0];
00449 root.fullCategoryPath = "/";
00450 root.categoryLabel = "/";
00451 root.allChildrenFetched = false;
00452
00453 QList<int> wantedProps = minimalistEntryPropIds();
00454 KLFLibResourceEngine::Query q;
00455 q.orderPropId = pLastSortPropId;
00456 q.orderDirection = pLastSortOrder;
00457 if (pModel->pFlavorFlags & KLFLibModel::CategoryTree) {
00458
00459 KLFLib::PropertyMatch pmatch(KLFLibEntry::Category, KLFLib::StringMatch(QString("")));
00460 q.matchCondition = KLFLib::EntryMatchCondition::mkPropertyMatch(pmatch);
00461 }
00462 q.wantedEntryProperties = minimalistEntryPropIds();
00463 q.limit = pModel->pFetchBatchCount;
00464 KLFLibResourceEngine::QueryResult qr(KLFLibResourceEngine::QueryResult::FillEntryWithIdList);
00465
00466 klfDbgT("about to query resource...");
00467 int count = pModel->pResource->query(pModel->pResource->defaultSubResource(), q, &qr);
00468 klfDbgT("resource returned "<<count<<" entries.");
00469 if (count < 0) {
00470 qWarning()<<KLF_FUNC_NAME<<": query() returned an error.";
00471
00472 }
00473 if (count < pModel->pFetchBatchCount) {
00474
00475 klfDbg("all children have been fetched.") ;
00476 root.allChildrenFetched = true;
00477 }
00478 const QList<KLFLibResourceEngine::KLFLibEntryWithId>& everything = qr.entryWithIdList;
00479 QList<KLFLibResourceEngine::KLFLibEntryWithId>::const_iterator it;
00480
00481 k = 0;
00482 for (it = everything.begin(); it != everything.end(); ++it) {
00483 const KLFLibResourceEngine::KLFLibEntryWithId& ewid = *it;
00484 klfDbgT( "Adding entry id="<<ewid.id<<"; entry="<<ewid.entry ) ;
00485 EntryNode e;
00486 e.entryid = ewid.id;
00487 e.minimalist = true;
00488 e.entry = ewid.entry;
00489 treeInsertEntry(e, true);
00490
00491 #ifndef Q_WS_MAC
00492 if (k % 10 == 0)
00493 progressReporter.doReportProgress((++k) * 100 / everything.size());
00494 #endif
00495 }
00496
00497 if (pModel->pFlavorFlags & KLFLibModel::CategoryTree) {
00498
00499 klfDbgT("About to query categories...");
00500 QVariantList vcatlist = pModel->pResource->queryValues(pModel->pResource->defaultSubResource(),
00501 KLFLibEntry::Category);
00502 klfDbgT("... got categories. inserting them ...");
00503 for (QVariantList::const_iterator vcit = vcatlist.begin(); vcit != vcatlist.end(); ++vcit) {
00504 QString cat = (*vcit).toString();
00505 if (cat.isEmpty() || cat == "/")
00506 continue;
00507
00508 QStringList catelements = cat.split('/', QString::SkipEmptyParts);
00509 int i = cacheFindCategoryLabel(catelements, true, false, false);
00510 if (i < 0) {
00511 qWarning()<<KLF_FUNC_NAME<<": Failed to create category node for category "<<cat;
00512 }
00513
00514 insertCategoryStringInSuggestionCache(catelements);
00515 }
00516 klfDbgT("... ins catnodes done.") ;
00517 }
00518
00519 fullDump();
00520
00521 pModel->reset();
00522
00523 klfDbg("restoring persistent indexes ...");
00524 QModelIndexList newPersistentIndexes = pModel->newPersistentIndexList(persistentIndexIds);
00525
00526 pModel->changePersistentIndexList(persistentIndexes, newPersistentIndexes);
00527 klfDbg("... done restoring persistent indexes.");
00528
00529 klfDbgT( " end of func" ) ;
00530 }
00531
00532
00533 QModelIndex KLFLibModelCache::createIndexFromId(NodeId nodeid, int row, int column)
00534 {
00535 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
00536
00537 if ( ! nodeid.valid() || nodeid == NodeId::rootNode())
00538 return QModelIndex();
00539
00540
00541 if ( row < 0 ) {
00542 row = getNodeRow(nodeid);
00543 }
00544
00545
00546
00547 klfDbg( ": nodeid="<<nodeid<<"; row="<<row<<"; col="<<column ) ;
00548
00549
00550 Node node = getNode(nodeid);
00551 NodeId parentid = node.parent;
00552 if (!parentid.valid())
00553 parentid = NodeId::rootNode();
00554
00555
00556 klfDbg("row="<<row) ;
00557 while ( getNode(parentid).children.size() <= row && canFetchMore(parentid) ) {
00558 klfDbgT(": need to fetch more children/size="
00559 <<getNode(parentid).children.size()<<"<row="<<row<<" !");
00560 fetchMore(parentid);
00561 }
00562
00563
00564 return pModel->createIndex(row, column, nodeid.universalId());
00565 }
00566
00567
00568 KLFLibModelCache::NodeId KLFLibModelCache::getNodeForIndex(const QModelIndex& index)
00569 {
00570 if ( ! index.isValid() )
00571 return NodeId();
00572 NodeId n = NodeId::fromUID(index.internalId());
00573
00574 if (n.kind == EntryKind) {
00575 if (n.index < 0 || n.index >= pEntryCache.size()) {
00576 qWarning()<<KLF_FUNC_NAME<<": Invalid entry node reference: "<<n;
00577 return NodeId();
00578 }
00579 } else if (n.kind == CategoryLabelKind) {
00580 if (n.index < 0 || n.index >= pCategoryLabelCache.size()) {
00581 qWarning()<<KLF_FUNC_NAME<<": Invalid category label node reference: "<<n;
00582 return NodeId();
00583 }
00584 } else {
00585 qWarning()<<KLF_FUNC_NAME<<": Invalid node kind: "<<n;
00586 return NodeId();
00587 }
00588 return n;
00589 }
00590
00591 KLFLibModelCache::Node KLFLibModelCache::getNode(NodeId nodeid)
00592 {
00593 if (!nodeid.valid())
00594 return CategoryLabelNode();
00595 Node &n = getNodeRef(nodeid);
00596 return n;
00597 }
00598 KLFLibModelCache::Node& KLFLibModelCache::getNodeRef(NodeId nodeid)
00599 {
00600 if (!nodeid.valid()) {
00601 qWarning()<<"KLFLibModelCache::getNodeRef: Invalid Node Id: "<<nodeid;
00602 return pInvalidEntryNode;
00603 }
00604 if (nodeid.kind == EntryKind) {
00605 if (nodeid.index < 0 || nodeid.index >= pEntryCache.size()) {
00606 qWarning()<<"KLFLibModelCache::getNodeRef: Invalid Entry Node Id: "<<nodeid<<" : index out of range!";
00607 return pInvalidEntryNode;
00608 }
00609 return pEntryCache[nodeid.index];
00610 } else if (nodeid.kind == CategoryLabelKind) {
00611 if (nodeid.index < 0 || nodeid.index >= pCategoryLabelCache.size()) {
00612 qWarning()<<"KLFLibModelCache::getNodeRef: Invalid Category Label Node Id: "<<nodeid
00613 <<" : index out of range!";
00614 return pInvalidEntryNode;
00615 }
00616 return pCategoryLabelCache[nodeid.index];
00617 }
00618 qWarning("KLFLibModelCache::getNodeRef(): Invalid kind: %d (index=%d)\n", nodeid.kind, nodeid.index);
00619 return pInvalidEntryNode;
00620 }
00621 KLFLibModelCache::EntryNode& KLFLibModelCache::getEntryNodeRef(NodeId nodeid, bool enforceNotMinimalist)
00622 {
00623 static EntryNode dummyerrornode;
00624 if (!nodeid.valid() || nodeid.kind != EntryKind ||
00625 nodeid.index < 0 || nodeid.index >= pEntryCache.size()) {
00626 qWarning()<<"KLFLibModelCache::getEntryNodeRef: Invalid Entry Node "<<nodeid<<"!";
00627 return dummyerrornode;
00628 }
00629 if (enforceNotMinimalist && pEntryCache[nodeid.index].minimalist)
00630 ensureNotMinimalist(nodeid);
00631
00632 return pEntryCache[nodeid.index];
00633 }
00634
00635 KLFLibModelCache::CategoryLabelNode& KLFLibModelCache::getCategoryLabelNodeRef(NodeId nodeid)
00636 {
00637 if (!nodeid.valid() || nodeid.kind != CategoryLabelKind ||
00638 nodeid.index < 0 || nodeid.index >= pCategoryLabelCache.size()) {
00639 qWarning()<<"KLFLibModelCache::getCat.LabelNode: Invalid Category Label Node "<<nodeid<<"!";
00640 return pCategoryLabelCache[0];
00641 }
00642 return pCategoryLabelCache[nodeid.index];
00643 }
00644
00645 int KLFLibModelCache::getNodeRow(NodeId node)
00646 {
00647 if ( ! node.valid() )
00648 return -1;
00649 if ( node == NodeId::rootNode() )
00650 return 0;
00651
00652 Node n = getNode(node);
00653
00654 NodeId pparentid = n.parent;
00655 if ( !pparentid.valid() ) {
00656
00657 qWarning()<<KLF_FUNC_NAME<<": Found parentless non-root node: "<<node;
00658 return 0;
00659 }
00660 Node pparent = getNode(pparentid);
00661
00662 int k;
00663 for (k = 0; k < pparent.children.size(); ++k)
00664 if (pparent.children[k] == node)
00665 return k;
00666
00667
00668 qWarning()<<KLF_FUNC_NAME<<": Unable to get node row: parent-child one-way broken!! node="<<node;
00669 return -1;
00670 }
00671
00672 void KLFLibModelCache::ensureNotMinimalist(NodeId p, int countdown)
00673 {
00674 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00675
00676 NodeId n;
00677
00678 QMap<KLFLib::entryId, NodeId> wantedIds;
00679 if (countdown < 0)
00680 countdown = pModel->pFetchBatchCount;
00681
00682
00683 n = p;
00684 for (; n.valid() && countdown-- > 0; n = nextNode(n)) {
00685 if (n.kind == CategoryLabelKind) {
00686 ++countdown;
00687 continue;
00688 }
00689 if (n.kind == EntryKind) {
00690 EntryNode en = getEntryNodeRef(n);
00691 if (en.minimalist)
00692 wantedIds[en.entryid] = n;
00693 continue;
00694 }
00695 qWarning()<<KLF_FUNC_NAME<<": Got unknown kind="<<n.kind;
00696 }
00697
00698 QList<KLFLibResourceEngine::KLFLibEntryWithId> updatedentries =
00699 pModel->pResource->entries(wantedIds.keys(), QList<int>());
00700 int k;
00701 for (k = 0; k < updatedentries.size(); ++k) {
00702 KLFLib::entryId eid = updatedentries[k].id;
00703 if ( ! wantedIds.contains(eid) ) {
00704 qWarning()<<KLF_FUNC_NAME<<" got unrequested updated entry ID ?! id="<<eid;
00705 continue;
00706 }
00707 NodeId nid = wantedIds[eid];
00708 pEntryCache[nid.index].entry = updatedentries[k].entry;
00709 pEntryCache[nid.index].minimalist = false;
00710 }
00711 klfDbg( ": updated entries "<<wantedIds.keys() ) ;
00712 }
00713
00714 bool KLFLibModelCache::canFetchMore(NodeId parentId)
00715 {
00716 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00717 if (pIsFetchingMore)
00718 return false;
00719
00720 if (!parentId.valid())
00721 parentId = NodeId::rootNode();
00722
00723 klfDbg("parentId="<<parentId) ;
00724
00725 const Node& node = getNodeRef(parentId);
00726
00727 klfDbg("node="<<node) ;
00728
00729 if (!node.allChildrenFetched)
00730 return true;
00731
00732 klfDbg("cannot fetchmore.") ;
00733 return false;
00734 }
00735 void KLFLibModelCache::fetchMore(NodeId n, int fetchBatchCount)
00736 {
00737 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME);
00738 klfDbg( "\t parentId: n="<<n<<"; valid="<<n.valid() <<"; url="<<pModel->url() ) ;
00739
00740 if (fetchBatchCount < 0)
00741 fetchBatchCount = pModel->pFetchBatchCount;
00742
00743 if (pIsFetchingMore)
00744 return;
00745 pIsFetchingMore = true;
00746
00747
00748
00749 if (!n.valid())
00750 n = NodeId::rootNode();
00751
00752 if (n.kind != CategoryLabelKind) {
00753 klfDbg("can't fetch more in this node kind. n="<<n);
00754 qWarning()<<KLF_FUNC_NAME<<": Can't fetch more children of a non-category-label node.";
00755 return;
00756 }
00757
00758 CategoryLabelNode& noderef = getCategoryLabelNodeRef(n);
00759 klfDbg( "\t -> n="<<n<<"; noderef: kind="<<noderef.kind<<", allChildrenFetched="<<noderef.allChildrenFetched ) ;
00760
00761 if (noderef.allChildrenFetched) {
00762
00763 klfDbg("can't fetch more: all children are fetched! noderef="<<noderef<<"; n (the id)="<<n) ;
00764
00765 pIsFetchingMore = false;
00766 return;
00767 }
00768
00769
00770 KLFLibResourceEngine::Query q;
00771 if (pModel->pFlavorFlags & KLFLibModel::CategoryTree) {
00772 QString c = KLFLibEntry::normalizeCategoryPath(noderef.fullCategoryPath);
00773 KLFLib::PropertyMatch pmatch(KLFLibEntry::Category, KLFLib::StringMatch(c));
00774 q.matchCondition = KLFLib::EntryMatchCondition::mkPropertyMatch(pmatch);
00775 }
00776 q.orderPropId = pLastSortPropId;
00777 q.orderDirection = pLastSortOrder;
00778 q.limit = pModel->pFetchBatchCount;
00779 q.skip = noderef.children.size();
00780 q.wantedEntryProperties = minimalistEntryPropIds();
00781 KLFLibResourceEngine::QueryResult qr(KLFLibResourceEngine::QueryResult::FillEntryWithIdList);
00782
00783 int count = pModel->pResource->query(pModel->pResource->defaultSubResource(), q, &qr);
00784 if (count < 0) {
00785 qWarning()<<KLF_FUNC_NAME<<": error fetching more results: count is "<<count;
00786 pIsFetchingMore = false;
00787 return;
00788 }
00789
00796
00797
00798
00799 pModel->startLayoutChange(false);
00800 pModel->beginInsertRows(createIndexFromId(n, -1, 0), noderef.children.size(),
00801 noderef.children.size() + qr.entryWithIdList.size()-1);
00802
00803
00804 if (count < q.limit) {
00805 noderef.allChildrenFetched = true;
00806 }
00807
00808 int k;
00809 for (k = 0; k < qr.entryWithIdList.size(); ++k) {
00810 const KLFLibResourceEngine::KLFLibEntryWithId& ewid = qr.entryWithIdList[k];
00811 EntryNode e;
00812 e.entryid = ewid.id;
00813 e.minimalist = true;
00814 e.entry = ewid.entry;
00815 e.parent = n;
00816 pEntryCache.append(e);
00817 NodeId entryindex;
00818 entryindex.kind = EntryKind;
00819 entryindex.index = pEntryCache.size()-1;
00820
00821 klfDbg("appending "<<e<<" in category node.") ;
00822
00823 noderef.children.append(entryindex);
00824 }
00825
00826 klfDbg("Fetched more. About to notify view of end of rows inserted ... meanwile the dump:") ;
00827 fullDump();
00828
00829 pModel->endInsertRows();
00830 klfDbg("signal emitted. restore persistent indexes...") ;
00831 pModel->endLayoutChange(false);
00832
00833 klfDbg("views notified, persistent indexes restored.") ;
00834
00835 pIsFetchingMore = false;
00836 }
00837
00838
00839
00840 void KLFLibModelCache::updateData(const QList<KLFLib::entryId>& entryIdList, int modifyType)
00841 {
00842 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00843 klfDbg( "modifyType="<<modifyType<<" entryIdList="<<entryIdList ) ;
00844
00845 if (modifyType == KLFLibResourceEngine::UnknownModification) {
00846 klfDbg("Performing full refresh.") ;
00847 rebuildCache();
00848 return;
00849 }
00850
00851 if (entryIdList.size() > 10 &&
00852 (entryIdList.size() > pEntryCache.size()/3 || entryIdList.size() > 100)) {
00853
00854 klfDbg("Performing full refresh.") ;
00855 rebuildCache();
00856 return;
00857 }
00858
00859 #ifndef Q_WS_MAC
00860
00861 KLFProgressReporter progressReporter(0, entryIdList.size(), NULL);
00862 emit pModel->operationStartReportingProgress(&progressReporter,
00863 QObject::tr("Updating View...", "[[KLFLibModelCache, progress text]]"));
00864 progressReporter.doReportProgress(0);
00865 #endif
00866
00867 switch (modifyType) {
00868 case KLFLibResourceEngine::InsertData:
00869 {
00870 QList<KLFLibResourceEngine::KLFLibEntryWithId> entryList = pModel->pResource->entries(entryIdList);
00871 int k;
00872 for (k = 0; k < entryList.size(); ++k) {
00873 EntryNode en;
00874 en.entryid = entryList[k].id;
00875 en.minimalist = false;
00876 en.entry = entryList[k].entry;
00879 treeInsertEntry(en);
00880 qDebug("%s: entry ID %d inserted", KLF_FUNC_NAME, entryIdList[k]);
00881 #ifndef Q_WS_MAC
00882 if (k % 20 == 0)
00883 progressReporter.doReportProgress(k+1);
00884 #endif
00885 }
00886 break;
00887 }
00888 case KLFLibResourceEngine::ChangeData:
00889 {
00890 QList<KLFLibResourceEngine::KLFLibEntryWithId> entryList = pModel->pResource->entries(entryIdList);
00891 int k;
00892 for (k = 0; k < entryIdList.size(); ++k) {
00893 klfDbg("modifying entry ID="<<entryIdList[k]<<", modif."<<k) ;
00894 NodeId n = findEntryId(entryIdList[k]);
00895 if (!n.valid()) {
00896 qWarning()<<KLF_FUNC_NAME<<": n is invalid! (kind="<<n.kind<<", index="<<n.index<<")";
00897 continue;
00898 }
00899 KLFLibEntry oldentry = pEntryCache[n.index].entry;
00900 KLFLibEntry newentry = entryList[k].entry;
00901 klfDbg("entry change: old="<<oldentry<<"; new="<<newentry) ;
00902
00903 if (newentry.category() != oldentry.category() && (pModel->pFlavorFlags & KLFLibModel::CategoryTree)) {
00904 pModel->startLayoutChange(false);
00905 EntryNode entrynode = treeTakeEntry(n, true);
00906
00907
00908
00909
00910 entrynode.entryid = entryIdList[k];
00911 entrynode.entry = newentry;
00912
00913 treeInsertEntry(entrynode);
00914 pModel->endLayoutChange(false);
00915 QModelIndex idx = createIndexFromId(n, -1, 0);
00916 emit pModel->dataChanged(idx, idx);
00917 } else {
00918
00919 pEntryCache[n.index].entry = newentry;
00920 QModelIndex idx = createIndexFromId(n, -1, 0);
00921 emit pModel->dataChanged(idx, idx);
00922 }
00923 #ifndef Q_WS_MAC
00924 if (k % 20 == 0)
00925 progressReporter.doReportProgress(k+1);
00926 #endif
00927 }
00928 break;
00929 }
00930 case KLFLibResourceEngine::DeleteData:
00931 {
00932 int k;
00933 for (k = 0; k < entryIdList.size(); ++k) {
00934 qDebug("%s: deleting entry ID=%d.", KLF_FUNC_NAME, entryIdList[k]);
00935
00936 NodeId n = findEntryId(entryIdList[k]);
00937 if (!n.valid()) {
00938 qWarning()<<KLF_FUNC_NAME<<": n not valid! n=(kind="<<n.kind<<", index="<<n.index<<")";
00939 continue;
00940 }
00941 (void) treeTakeEntry(n);
00942 #ifndef Q_WS_MAC
00943 if (k % 20 == 0)
00944 progressReporter.doReportProgress(k+1);
00945 #endif
00946 }
00947 break;
00948 }
00949 default:
00950 {
00951 qWarning()<<KLF_FUNC_NAME<<": Bad modify-type parameter: "<<modifyType;
00952 rebuildCache();
00953 return;
00954 }
00955 }
00956
00957
00958 klfDbg( ": udpated; full tree dump:" ) ;
00959 fullDump();
00960 }
00961
00962
00963 void KLFLibModelCache::treeInsertEntry(const EntryNode& entrynode, bool rebuildingcache)
00964 {
00965 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
00966
00967 bool notifyQtApi = !rebuildingcache;
00968 klfDbg( "entrynode="<<entrynode<<",notifyQtApi="<<notifyQtApi<<"" ) ;
00969
00970
00971
00972
00973
00974 QString category = entrynode.entry.category();
00975 QStringList catelements = category.split('/', QString::SkipEmptyParts);
00976 insertCategoryStringInSuggestionCache(catelements);
00977
00978
00979
00980 IndexType catindex;
00981 if (pModel->displayType() == KLFLibModel::LinearList) {
00982
00983 catindex = 0;
00984 } else if (pModel->displayType() == KLFLibModel::CategoryTree) {
00985
00986 catindex = cacheFindCategoryLabel(catelements, true, notifyQtApi, rebuildingcache?false:true);
00987 } else {
00988 qWarning("Flavor Flags have unknown display type! flavorFlags=%#010x", pModel->pFlavorFlags);
00989 catindex = 0;
00990 }
00991
00992 NodeId parentid = NodeId(CategoryLabelKind, catindex);
00993
00994
00995 int index = pEntryCache.insertNewNode(entrynode);
00996 NodeId n = NodeId(EntryKind, index);
00997
00998
00999 pEntryCache[index].parent = NodeId();
01000
01001
01002
01003 Node& parentref = getNodeRef(parentid);
01004 QList<NodeId> & childlistref = parentref.children;
01005 int insertPos;
01006 if (rebuildingcache || pLastSortPropId < 0) {
01007 insertPos = childlistref.size();
01008 } else {
01009 KLFLibModelSorter srt =
01010 KLFLibModelSorter(this, pModel->pEntrySorter, pModel->pFlavorFlags & KLFLibModel::GroupSubCategories);
01011
01012
01013 bool retry;
01014 do {
01015 retry = false;
01016
01017 insertPos = qLowerBound(childlistref.begin(), childlistref.end(), n, srt) - childlistref.begin();
01018 if (insertPos > childlistref.size()-10 && canFetchMore(parentid)) {
01019 fetchMore(parentid);
01020 retry = true;
01021 }
01022 } while (retry);
01023
01024
01025 if (insertPos < childlistref.size() && childlistref[insertPos] == n)
01026 return;
01027 }
01028
01029 CategoryLabelNode &catLabelNodeRef = getCategoryLabelNodeRef(parentid);
01030
01031
01032 if (notifyQtApi) {
01033 QModelIndex parentidx = createIndexFromId(parentid, -1, 0);
01034 pModel->beginInsertRows(parentidx, insertPos, insertPos);
01035 }
01036
01037 qDebug("\tinserting (%d,%d) at pos %d in category '%s'", n.kind, n.index, insertPos,
01038 qPrintable(catLabelNodeRef.fullCategoryPath));
01039
01040 pEntryCache[n.index].parent = parentid;
01041
01042 childlistref.insert(insertPos, n);
01043
01044 if (notifyQtApi)
01045 pModel->endInsertRows();
01046 }
01047
01048 KLFLibModelCache::EntryNode KLFLibModelCache::treeTakeEntry(const NodeId& nodeid, bool notifyQtApi)
01049 {
01050 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01051
01052 klfDbg( "("<<nodeid<<","<<notifyQtApi<<")" ) ;
01053 NodeId n = nodeid;
01054
01055
01056 if (nodeid.kind != EntryKind) {
01057 qWarning()<<KLF_FUNC_NAME<<": nodeid="<<nodeid<<" does not reference an entry node!";
01058 return EntryNode();
01059 }
01060 EntryNode entrynode = getEntryNodeRef(nodeid);
01061
01062 klfDbg("The entrynode in question is "<<entrynode) ;
01063
01064 NodeId parentid;
01065 bool willRemoveParent;
01066 do {
01067 if (!n.valid())
01068 break;
01069 parentid = getNode(n).parent;
01070 if (n == NodeId::rootNode())
01071 break;
01072 klfDbg("Getting interested to remove entry ID="<<n<<", from its parent of id="<<parentid) ;
01073 if (parentid.kind != CategoryLabelKind) {
01074 qWarning()<<KLF_FUNC_NAME<<"("<<n<<"): Bad parent node kind: "<<parentid.kind<<"!";
01075 return entrynode;
01076 }
01077 QModelIndex parent = createIndexFromId(parentid, -1, 0);
01078 int childIndex = pCategoryLabelCache[parentid.index].children.indexOf(n);
01079 if (childIndex < 0) {
01080 qWarning()<<KLF_FUNC_NAME<<"("<<n<<"): !!?! bad child-parent relation, can't find "<<n
01081 <<" in child list "<<pCategoryLabelCache[parentid.index].children<<"; full dump:\n"
01082 <<"\tEntryCache = "<<pEntryCache<<"\n"
01083 <<"\tCat.Lbl.Cache = "<<pCategoryLabelCache;
01084 return entrynode;
01085 }
01086 if (notifyQtApi)
01087 pModel->beginRemoveRows(parent, childIndex, childIndex);
01088
01089 willRemoveParent = parentid.valid() && getNode(parentid).children.size() <= 1;
01090
01091 if (n.kind == EntryKind) {
01092 klfDbg("unlinking entry node "<<n);
01093 pEntryCache.unlinkNode(n);
01094 } else if (n.kind == CategoryLabelKind) {
01095 klfDbg("unlinking category label node "<<n);
01096 pCategoryLabelCache.unlinkNode(n);
01097 } else {
01098 qWarning()<<KLF_FUNC_NAME<<": unlinking elements: unknown node kind in id="<<n<<"!";
01099 }
01100
01101 Node & parentref = getNodeRef(parentid);
01102 klfDbg("removing child #"<<childIndex<<" from parent id="<<parentid<<"; parent itself is "<<parentref) ;
01103 parentref.children.removeAt(childIndex);
01104 if (notifyQtApi)
01105 pModel->endRemoveRows();
01106 n = parentid;
01107 } while (willRemoveParent);
01108
01109 return entrynode;
01110 }
01111
01112
01113
01114
01115 KLFLibModelCache::IndexType
01116 KLFLibModelCache::cacheFindCategoryLabel(QStringList catelements, bool createIfNotExists,
01117 bool notifyQtApi, bool newlyCreatedAreChildrenFetched)
01118 {
01119 klfDbg( "catelmnts="<<catelements<<", createIfNotExists="<<createIfNotExists<<", notifyQtApi="<<notifyQtApi ) ;
01120
01121 QString catelpath = catelements.join("/");
01122
01123 int i;
01124 for (i = 0; i < pCategoryLabelCache.size(); ++i) {
01125 if (pCategoryLabelCache.isAllocated(i) &&
01126 pCategoryLabelCache[i].parent.valid() &&
01127 pCategoryLabelCache[i].fullCategoryPath == catelpath) {
01128
01129 return i;
01130 }
01131 }
01132 if (catelements.isEmpty())
01133 return 0;
01134
01135
01136
01137 if ( ! createIfNotExists )
01138 return -1;
01139
01140 if (pModel->displayType() != KLFLibModel::CategoryTree) {
01141 qWarning("cacheFindCategoryLabel: but not in a category tree display type (flavor flags=%#010x)",
01142 pModel->pFlavorFlags);
01143 return 0;
01144 }
01145
01146 QStringList catelementsparent = catelements.mid(0, catelements.size()-1);
01147 IndexType parent_index = cacheFindCategoryLabel(catelementsparent, true, notifyQtApi);
01148
01149 KLFLibModelCache::KLFLibModelSorter srt =
01150 KLFLibModelCache::KLFLibModelSorter(this, pModel->pEntrySorter,
01151 pModel->pFlavorFlags & KLFLibModel::GroupSubCategories);
01152
01153
01154 CategoryLabelNode c;
01155 c.allChildrenFetched = newlyCreatedAreChildrenFetched;
01156 c.fullCategoryPath = catelpath;
01157 c.categoryLabel = catelements.last();
01158
01159 IndexType this_index = pCategoryLabelCache.insertNewNode(c);
01160 int insertPos;
01161 CategoryLabelNode & parentCatLabelNodeRef = pCategoryLabelCache[parent_index];
01162 QList<NodeId> & childlistref = parentCatLabelNodeRef.children;
01163 if (pLastSortPropId < 0) {
01164 insertPos = childlistref.size();
01165 } else {
01166
01167 insertPos = qLowerBound(childlistref.begin(), childlistref.end(),
01168 NodeId(CategoryLabelKind, this_index), srt) - childlistref.begin();
01169 }
01170 klfDbg( ": About to insert rows in "<<NodeId(CategoryLabelKind, parent_index)
01171 <<" at position "<<insertPos ) ;
01172 if (notifyQtApi) {
01173 QModelIndex parentidx = createIndexFromId(NodeId(CategoryLabelKind, parent_index), -1, 0);
01174 pModel->beginInsertRows(parentidx, insertPos, insertPos);
01175 }
01176 qDebug("%s: Inserting this_index=%d in parent_index=%d 's children", KLF_FUNC_NAME, this_index,
01177 parent_index);
01178
01179 childlistref.insert(insertPos, NodeId(CategoryLabelKind, this_index));
01180 pCategoryLabelCache[this_index].parent = NodeId(CategoryLabelKind, parent_index);
01181
01182 if (notifyQtApi)
01183 pModel->endInsertRows();
01184
01185
01186 return this_index;
01187 }
01188
01189 QString KLFLibModelCache::nodeValue(NodeId n, int entryProperty)
01190 {
01191
01192
01193
01194 if (!n.valid() || n.isRoot())
01195 return QString();
01196 if (entryProperty < 0) {
01197 qWarning()<<KLF_FUNC_NAME<<": invalid entry property ID : "<<entryProperty;
01198 return QString();
01199 }
01200 if (n.kind == EntryKind) {
01201 EntryNode en = getEntryNodeRef(n);
01202
01203 return pModel->entrySorter()->entryValue(en.entry, entryProperty);
01204 }
01205 if (n.kind == CategoryLabelKind)
01206 return getCategoryLabelNodeRef(n).categoryLabel;
01207
01208 qWarning()<<KLF_FUNC_NAME<<": Bad Item Kind: "<<n;
01209 return QString();
01210 }
01211
01212
01213 void KLFLibModelCache::sortCategory(NodeId category, KLFLibModelSorter *sorter, bool rootCall)
01214 {
01215 bool requireSimpleReverse = false;
01216
01217
01218 if (sorter->entrySorter()->propId() == pLastSortPropId) {
01219
01220 if (sorter->entrySorter()->order() == pLastSortOrder) {
01221
01222 return;
01223 } else {
01224
01225
01226 requireSimpleReverse = true;
01227 }
01228 }
01229
01230 int k;
01231
01232
01233
01234
01235
01236 if (category.kind != CategoryLabelKind)
01237 return;
01238 if (category.index < 0 || category.index >= pCategoryLabelCache.size())
01239 return;
01240
01241 if (sorter->entrySorter()->propId() < 0)
01242 return;
01243
01244 QList<NodeId>& childlistref = pCategoryLabelCache[category.index].children;
01245 if (requireSimpleReverse) {
01246
01247 int N = childlistref.size();
01248 int firstEntryInd = 0;
01249 if (pModel->pFlavorFlags & KLFLibModel::GroupSubCategories) {
01250 for (firstEntryInd = 0; firstEntryInd < N &&
01251 childlistref[firstEntryInd].kind != EntryKind; ++firstEntryInd)
01252 ;
01253
01254 }
01255
01256 for (k = 0; k < (N-firstEntryInd)/2; ++k)
01257 qSwap(childlistref[firstEntryInd+k], childlistref[N-k-1]);
01258 } else {
01259 qSort(childlistref.begin(), childlistref.end(), *sorter);
01260 }
01261
01262
01263 for (k = 0; k < childlistref.size(); ++k)
01264 if (childlistref[k].kind == CategoryLabelKind)
01265 sortCategory(childlistref[k], sorter, false );
01266
01267 if (rootCall) {
01268 pLastSortPropId = sorter->entrySorter()->propId();
01269 pLastSortOrder = sorter->entrySorter()->order();
01270 }
01271 }
01272
01273
01274 KLFLibModelCache::NodeId KLFLibModelCache::nextNode(NodeId n)
01275 {
01276
01277
01278
01279 if (!n.valid()) {
01280
01281 n = NodeId::rootNode();
01282 }
01283
01284 Node nn = getNode(n);
01285 if (nn.children.size() > 0) {
01286 return nn.children[0];
01287 }
01288 if (!nn.allChildrenFetched && canFetchMore(n)) {
01289
01290 fetchMore(n);
01291
01292 return nextNode(n);
01293 }
01294
01295 NodeId parentid;
01296 while ( (parentid = nn.parent).valid() ) {
01297 Node parent = getNode(parentid);
01298 int row = getNodeRow(n);
01299 if (row+1 < parent.children.size()) {
01300
01301 return parent.children[row+1];
01302 }
01303 if (!parent.allChildrenFetched && canFetchMore(parentid)) {
01304
01305 fetchMore(parentid);
01306
01307 return nextNode(n);
01308 }
01309
01310 n = parentid;
01311 nn = parent;
01312 }
01313
01314 return NodeId();
01315 }
01316
01317 KLFLibModelCache::NodeId KLFLibModelCache::prevNode(NodeId n)
01318 {
01319 if (!n.valid() || n.isRoot()) {
01320
01321 return lastNode(NodeId());
01322 }
01323
01324 NodeId parentId = getNode(n).parent;
01325 Node parent = getNode(parentId);
01326 int row = getNodeRow(n);
01327 if (row > 0) {
01328
01329 return lastNode(parent.children[row-1]);
01330 }
01331
01332
01333 if (parentId == NodeId::rootNode())
01334 return NodeId();
01335
01336 return parentId;
01337 }
01338
01339 KLFLibModelCache::NodeId KLFLibModelCache::lastNode(NodeId n)
01340 {
01341 if (!n.valid())
01342 n = NodeId::rootNode();
01343
01344 Node nn = getNode(n);
01345
01346
01347
01348 while (!nn.allChildrenFetched) {
01349 if (!canFetchMore(n)) {
01350 qWarning()<<KLF_FUNC_NAME<<": internal error: node "<<n<<", node="<<nn
01351 <<" has allChildrenFetched=false, but can't fetch more!";
01352 break;
01353 }
01354 fetchMore(n);
01355 nn = getNode(n);
01356 }
01357
01358 if (nn.children.size() == 0)
01359 return n;
01360
01361
01362 return lastNode(nn.children[nn.children.size()-1]);
01363 }
01364
01365
01366 QList<KLFLib::entryId> KLFLibModelCache::entryIdList(const QModelIndexList& indexlist)
01367 {
01368
01369
01370 QList<KLFLib::entryId> idList;
01371 int k;
01372 QList<NodeId> nodeIds;
01373
01374 for (k = 0; k < indexlist.size(); ++k) {
01375 NodeId n = getNodeForIndex(indexlist[k]);
01376 if ( !n.valid() || n.kind != EntryKind)
01377 continue;
01378 if ( nodeIds.contains(n) )
01379 continue;
01380 nodeIds << n;
01381 idList << getEntryNodeRef(n).entryid;
01382 }
01383 return idList;
01384 }
01385
01386
01387
01388 QList<KLFLib::entryId> KLFLibModelCache::entryIdForIndexList(const QModelIndexList& indexlist)
01389 {
01390
01391
01392 QList<KLFLib::entryId> eidlist;
01393 int k;
01394 for (k = 0; k < indexlist.size(); ++k) {
01395 NodeId node = getNodeForIndex(indexlist[k]);
01396 if ( !node.valid() || node.kind != EntryKind ) {
01397 eidlist << (KLFLib::entryId) -1;
01398 continue;
01399 }
01400 eidlist << getEntryNodeRef(node).entryid;
01401 }
01402 return eidlist;
01403 }
01404 QModelIndexList KLFLibModelCache::findEntryIdList(const QList<KLFLib::entryId>& eidlist)
01405 {
01406 klfDbg( ": eidlist="<<eidlist ) ;
01407 int k;
01408 int count = 0;
01409 QModelIndexList indexlist;
01410
01411 for (k = 0; k < eidlist.size(); ++k)
01412 indexlist << QModelIndex();
01413
01414
01415 for (k = 0; k < pEntryCache.size(); ++k) {
01416 if (!pEntryCache[k].entryIsValid())
01417 continue;
01418 int i = eidlist.indexOf(pEntryCache[k].entryid);
01419 if (i >= 0) {
01420 indexlist[i] = createIndexFromId(NodeId(EntryKind, k), -1, 0);
01421 if (++count == eidlist.size())
01422 break;
01423 }
01424 }
01425 return indexlist;
01426 }
01427
01428 KLFLibModelCache::NodeId KLFLibModelCache::findEntryId(KLFLib::entryId eId)
01429 {
01430 klfDbg("eId="<<eId) ;
01431 int k;
01432 for (k = 0; k < pEntryCache.size(); ++k)
01433 if (pEntryCache[k].entryid == eId && pEntryCache[k].entryIsValid())
01434 return NodeId(EntryKind, k);
01435
01436 klfDbg("...not found.") ;
01437 return NodeId();
01438 }
01439
01440
01441 void KLFLibModelCache::fullDump()
01442 {
01443 #ifdef KLF_DEBUG
01444 int k;
01445 qDebug("---------------------------------------------------------");
01446 qDebug("------------- FULL CACHE DUMP ---------------------------");
01447 qDebug("---------------------------------------------------------");
01448 qDebug(" ");
01449 qDebug("Entry cache dump:");
01450 for (k = 0; k < pEntryCache.size(); ++k)
01451 qDebug()<<"#"<<k<<": "<<pEntryCache[k];
01452 qDebug(" ");
01453 qDebug("Category Label cache dump: ");
01454 for (k = 0; k < pCategoryLabelCache.size(); ++k)
01455 qDebug()<<"#"<<k<<": "<<pCategoryLabelCache[k];
01456 qDebug(" ");
01457 dumpNodeTree(NodeId::rootNode());
01458 qDebug(" ");
01459 qDebug("---------------------------------------------------------");
01460 qDebug("---------------------------------------------------------");
01461 qDebug("---------------------------------------------------------");
01462 #endif
01463 }
01464
01465 void KLFLibModelCache::dumpNodeTree(NodeId node, int indent)
01466 {
01467 #ifdef KLF_DEBUG
01468
01469 if (indent == 0) {
01470 qDebug(" ");
01471 qDebug("---------------- NODE TREE DUMP -------------------------");
01472 }
01473 char sindent[] = " + ";
01474 if (indent < (signed)strlen(sindent))
01475 sindent[indent] = '\0';
01476
01477 if (!node.valid())
01478 qDebug() << sindent << "(Invalid Node)";
01479
01480 EntryNode en;
01481 CategoryLabelNode cn;
01482 switch (node.kind) {
01483 case EntryKind:
01484 en = getEntryNodeRef(node);
01485 qDebug() << sindent << node <<"\n"<<sindent<<"\t\t"<<en;
01486 break;
01487 case CategoryLabelKind:
01488 cn = getCategoryLabelNodeRef(node);
01489 qDebug() << sindent << node << "\n"<<sindent<<"\t\t"<<cn;
01490 break;
01491 default:
01492 qDebug() << sindent << node << "\n"<<sindent<<"\t\t*InvalidNodeKind*(kind="<<node.kind<<")";
01493 }
01494
01495 if (node.valid()) {
01496 Node n = getNode(node);
01497 int k;
01498 for (k = 0; k < n.children.size(); ++k) {
01499 dumpNodeTree(getNode(node).children[k], indent+4);
01500 }
01501 }
01502
01503 if (indent == 0) {
01504 qDebug("---------------------------------------------------------");
01505 qDebug("---------------------------------------------------------");
01506 }
01507
01508 #endif
01509 }
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520 KLFLibModel::KLFLibModel(KLFLibResourceEngine *engine, uint flavorFlags, QObject *parent)
01521 : QAbstractItemModel(parent), pFlavorFlags(flavorFlags)
01522 {
01523 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01524
01525
01526
01527
01528
01529
01530
01531 setFetchBatchCount(30);
01532
01533
01534 pEntrySorter = new KLFLibEntrySorter(KLFLibEntry::DateTime, Qt::DescendingOrder);
01535
01536 pCache = new KLFLibModelCache(this);
01537
01538
01539 setResource(engine);
01540
01541
01542
01543
01544 }
01545
01546 KLFLibModel::~KLFLibModel()
01547 {
01548 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01549 delete pCache;
01550 if (pEntrySorter)
01551 delete pEntrySorter;
01552 }
01553
01554 void KLFLibModel::setResource(KLFLibResourceEngine *resource)
01555 {
01556 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01557
01558 KLF_DEBUG_ASSIGN_SAME_REF_INSTANCE(pCache) ;
01559
01560 pResource = resource;
01561 updateCacheSetupModel();
01562 }
01563
01564 QUrl KLFLibModel::url() const
01565 {
01566 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01567 if (pResource == NULL) {
01568 qWarning()<<KLF_FUNC_NAME<<": resource is NULL!";
01569 return QUrl();
01570 }
01571 if ((pResource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResources) == 0)
01572 return pResource->url();
01573
01574
01575 return pResource->url(KLFLibResourceEngine::WantUrlDefaultSubResource);
01576 }
01577
01578
01579
01580 void KLFLibModel::setFlavorFlags(uint flags, uint modify_mask)
01581 {
01582 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01583 if ( (flags & modify_mask) == (pFlavorFlags & modify_mask) )
01584 return;
01585 uint other_flags = pFlavorFlags & ~modify_mask;
01586 pFlavorFlags = flags | other_flags;
01587
01588
01589 if (modify_mask & DisplayTypeMask) {
01590 updateCacheSetupModel();
01591 }
01592 if (modify_mask & GroupSubCategories) {
01593 int col = columnForEntryPropertyId(pEntrySorter->propId());
01594 Qt::SortOrder ord = pEntrySorter->order();
01595
01596 sort(-1, ord);
01597 sort(col, ord);
01598 }
01599 }
01600 uint KLFLibModel::flavorFlags() const
01601 {
01602 return pFlavorFlags;
01603 }
01604
01605 void KLFLibModel::prefetch(const QModelIndexList& indexes) const
01606 {
01607 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01608 int k;
01609 for (k = 0; k < indexes.size(); ++k) {
01610 if (!indexes[k].isValid())
01611 continue;
01612 KLFLibModelCache::NodeId p = pCache->getNodeForIndex(indexes[k]);
01613 if (!p.valid() || p.isRoot()) {
01614 klfDbg("Invalid index: indexes[k].row="<<indexes[k].row());
01615 continue;
01616 }
01617 pCache->ensureNotMinimalist(p);
01618 }
01619 }
01620
01621 QVariant KLFLibModel::data(const QModelIndex& index, int role) const
01622 {
01623 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01624
01625
01626
01627 KLFLibModelCache::NodeId p = pCache->getNodeForIndex(index);
01628 if (!p.valid() || p.isRoot())
01629 return QVariant();
01630
01631
01632 KLFLibModelCache::Node thisNode = pCache->getNode(p);
01633 KLFLibModelCache::NodeId parent = thisNode.parent;
01634 KLFLibModelCache::Node parentNode = pCache->getNode(parent);
01635
01636 if (role == ItemKindItemRole)
01637 return QVariant::fromValue<int>(p.kind);
01638
01639 if (ItemKind(p.kind) == EntryKind) {
01640
01641 const KLFLibModelCache::EntryNode& ep = pCache->getEntryNodeRef(p);
01642
01643 if (role == EntryContentsTypeItemRole)
01644 return entryColumnContentsPropertyId(index.column());
01645 if (role == EntryIdItemRole)
01646 return QVariant::fromValue<KLFLib::entryId>(ep.entryid);
01647
01648 if (role == Qt::ToolTipRole || role == Qt::DisplayRole) {
01649 int propId = entryColumnContentsPropertyId(index.column());
01650 if (propId == KLFLibEntry::Preview)
01651 propId = KLFLibEntry::Tags;
01652 role = entryItemRole(propId);
01653
01654 }
01655
01656
01657 if (role < Qt::UserRole)
01658 return QVariant();
01659
01660
01661
01662 KLFLibEntry entry = ep.entry;
01663
01664 if ( ! pCache->minimalistEntryPropIds().contains(entryPropIdForItemRole(role)) &&
01665 ep.minimalist) {
01666
01667 pCache->ensureNotMinimalist(p);
01668 }
01669
01670 if (role == entryItemRole(KLFLibEntry::Latex))
01671 return entry.latex();
01672 if (role == entryItemRole(KLFLibEntry::DateTime))
01673 return entry.dateTime();
01674 if (role == entryItemRole(KLFLibEntry::Category))
01675 return entry.category();
01676 if (role == entryItemRole(KLFLibEntry::Tags))
01677
01678 return entry.tags();
01679 if (role == entryItemRole(KLFLibEntry::PreviewSize))
01680 return entry.previewSize();
01681
01682 entry = ep.entry;
01683
01684 if (role == FullEntryItemRole)
01685 return QVariant::fromValue(entry);
01686
01687 if (role == entryItemRole(KLFLibEntry::Preview))
01688 return QVariant::fromValue<QImage>(entry.preview());
01689 if (role == entryItemRole(KLFLibEntry::Style))
01690 return QVariant::fromValue(entry.style());
01691
01692 return QVariant();
01693 }
01694 else if (ItemKind(p.kind) == CategoryLabelKind) {
01695
01696 const KLFLibModelCache::CategoryLabelNode& cp = pCache->getCategoryLabelNodeRef(p);
01697 if (role == Qt::ToolTipRole)
01698 return cp.fullCategoryPath;
01699 if (role == CategoryLabelItemRole)
01700 return cp.categoryLabel;
01701 if (role == FullCategoryPathItemRole)
01702 return cp.fullCategoryPath;
01703
01704 return QVariant();
01705 }
01706
01707
01708 return QVariant();
01709 }
01710 Qt::ItemFlags KLFLibModel::flags(const QModelIndex& index) const
01711 {
01712 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01713 Qt::ItemFlags flagdropenabled = 0;
01714 if ( index.column() == 0 &&
01715 (pResource->canModifyData(KLFLibResourceEngine::InsertData) ||
01716 pResource->canModifyData(KLFLibResourceEngine::ChangeData)) )
01717 flagdropenabled = Qt::ItemIsDropEnabled;
01718
01719 if (!index.isValid())
01720 return flagdropenabled;
01721
01722 KLFLibModelCache::NodeId p = pCache->getNodeForIndex(index);
01723 if (!p.valid())
01724 return 0;
01725 if (p.kind == KLFLibModelCache::EntryKind)
01726 return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled;
01727 if (p.kind == KLFLibModelCache::CategoryLabelKind)
01728 return Qt::ItemIsEnabled | flagdropenabled;
01729
01730 qWarning()<<KLF_FUNC_NAME<<": bad item kind! index-row="<<index.row()<<"; p="<<p;
01731
01732
01733 return 0;
01734 }
01735 bool KLFLibModel::hasChildren(const QModelIndex &parent) const
01736 {
01737 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01738 if (parent.column() > 0)
01739 return false;
01740
01741 KLFLibModelCache::NodeId p = pCache->getNodeForIndex(parent);
01742 if (!p.valid() || p.isRoot()) {
01743
01744 p = KLFLibModelCache::NodeId::rootNode();
01745 }
01746
01747 return !pCache->getNode(p).allChildrenFetched || pCache->getNode(p).children.size() > 0;
01748 }
01749 QVariant KLFLibModel::headerData(int section, Qt::Orientation orientation, int role) const
01750 {
01751 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01752 if (role == Qt::FontRole) {
01753 return qApp->font();
01754 }
01755 if (role == Qt::SizeHintRole && orientation == Qt::Horizontal) {
01756 switch (entryColumnContentsPropertyId(section)) {
01757 case KLFLibEntry::Preview:
01758 return QSize(280,30);
01759 case KLFLibEntry::Latex:
01760 return QSize(350,30);
01761 case KLFLibEntry::Category:
01762 case KLFLibEntry::Tags:
01763 return QSize(200,30);
01764 default:
01765 return QVariant();
01766 }
01767 }
01768 if (role == Qt::DisplayRole) {
01769 if (orientation == Qt::Horizontal)
01770 return KLFLibEntry().propertyNameForId(entryColumnContentsPropertyId(section));
01771 return QString("-");
01772 }
01773 return QVariant();
01774 }
01775
01776 bool KLFLibModel::hasIndex(int row, int column, const QModelIndex &parent) const
01777 {
01778 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01779
01780 return index(row, column, parent).isValid();
01781 }
01782
01783 QModelIndex KLFLibModel::index(int row, int column, const QModelIndex &parent) const
01784 {
01785 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
01786
01787 const KLFLibModelCache::CategoryLabelNode& cat_p =
01788 pCache->getCategoryLabelNodeRef(KLFLibModelCache::NodeId::rootNode());
01789 KLFLibModelCache::CategoryLabelNode p = cat_p;
01790
01791 if (parent.isValid()) {
01792 KLFLibModelCache::NodeId pp = pCache->getNodeForIndex(parent);
01793 if (pp.kind != KLFLibModelCache::CategoryLabelKind)
01794 return QModelIndex();
01795 if (pp.valid())
01796 p = pCache->getCategoryLabelNodeRef(pp);
01797 }
01798 if (row < 0 || row >= p.children.size() || column < 0 || column >= columnCount(parent))
01799 return QModelIndex();
01800 klfDbgT(": row="<<row<<"; column="<<column<<"; parent="<<parent);
01801 return pCache->createIndexFromId(p.children[row], row, column);
01802 }
01803 QModelIndex KLFLibModel::parent(const QModelIndex &index) const
01804 {
01805 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
01806 klfDbgT(": requesting parent of index "<<index);
01807 KLFLibModelCache::NodeId p = pCache->getNodeForIndex(index);
01808 if ( !p.valid() )
01809 return QModelIndex();
01810 KLFLibModelCache::Node n = pCache->getNode(p);
01811 if ( ! n.parent.valid() )
01812 return QModelIndex();
01813 return KLF_DEBUG_TEE( pCache->createIndexFromId(n.parent, -1 , 0) ) ;
01814 }
01815 int KLFLibModel::rowCount(const QModelIndex &parent) const
01816 {
01817 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
01818
01819 if (parent.column() > 0)
01820 return 0;
01821
01822 KLFLibModelCache::NodeId p = pCache->getNodeForIndex(parent);
01823 if (!p.valid())
01824 p = KLFLibModelCache::NodeId::rootNode();
01825
01826 KLFLibModelCache::Node n = pCache->getNode(p);
01827 klfDbg( " parent="<<parent<<"; numchildren="<<n.children.size() ) ;
01828
01829 return n.children.size();
01830 }
01831
01832 int KLFLibModel::columnCount(const QModelIndex & ) const
01833 {
01834 return 5;
01835 }
01836 int KLFLibModel::entryColumnContentsPropertyId(int column) const
01837 {
01838
01839 switch (column) {
01840 case 0:
01841 return KLFLibEntry::Preview;
01842 case 1:
01843 return KLFLibEntry::Tags;
01844 case 2:
01845 return KLFLibEntry::Category;
01846 case 3:
01847 return KLFLibEntry::Latex;
01848 case 4:
01849 return KLFLibEntry::DateTime;
01850 default:
01851 return -1;
01852 }
01853 }
01854 int KLFLibModel::columnForEntryPropertyId(int entryPropertyId) const
01855 {
01856
01857 switch (entryPropertyId) {
01858 case KLFLibEntry::Preview:
01859 return 0;
01860 case KLFLibEntry::Tags:
01861 return 1;
01862 case KLFLibEntry::Category:
01863 return 2;
01864 case KLFLibEntry::Latex:
01865 return 3;
01866 case KLFLibEntry::DateTime:
01867 return 4;
01868 default:
01869 return -1;
01870 }
01871 }
01872
01873
01874 bool KLFLibModel::canFetchMore(const QModelIndex& parent) const
01875 {
01876 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01877
01878
01879 KLFLibModelCache::NodeId n = pCache->getNodeForIndex(parent);
01880 if (!n.valid())
01881 n = KLFLibModelCache::NodeId::rootNode();
01882
01883 return pCache->canFetchMore(pCache->getNodeForIndex(parent));
01884 }
01885 void KLFLibModel::fetchMore(const QModelIndex& parent)
01886 {
01887 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01888 pCache->fetchMore(pCache->getNodeForIndex(parent), pFetchBatchCount);
01889 }
01890
01891
01892 Qt::DropActions KLFLibModel::supportedDropActions() const
01893 {
01894 return Qt::CopyAction|Qt::MoveAction;
01895 }
01896
01897 QStringList KLFLibModel::mimeTypes() const
01898 {
01899 return QStringList() << "application/x-klf-internal-lib-move-entries"
01900 << KLFAbstractLibEntryMimeEncoder::allEncodingMimeTypes();
01901 }
01902 QMimeData *KLFLibModel::mimeData(const QModelIndexList& indlist) const
01903 {
01904 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01905
01906
01907 QModelIndexList indexes = indlist;
01908
01909
01910 KLFLibEntryList entries;
01911 QList<KLFLib::entryId> entryids;
01912 QList<KLFLibModelCache::NodeId> entriesnodeids;
01913 int k;
01914 for (k = 0; k < indexes.size(); ++k) {
01915 KLFLibModelCache::NodeId n = pCache->getNodeForIndex(indexes[k]);
01916 if (!n.valid() || n.isRoot())
01917 continue;
01918 if (n.kind != KLFLibModelCache::EntryKind)
01919 continue;
01920 if (entriesnodeids.contains(n))
01921 continue;
01922 const KLFLibModelCache::EntryNode& en = pCache->getEntryNodeRef(n);
01923 entries << pResource->entry(en.entryid);
01924 entryids << en.entryid;
01925 entriesnodeids << n;
01926 }
01927
01928
01929
01930
01931 QVariantMap vprop;
01932 QUrl myurl = url();
01933 vprop["Url"] = myurl;
01934
01935 QMimeData *mimedata = KLFAbstractLibEntryMimeEncoder::createMimeData(entries, vprop);
01936
01937 QByteArray internalmovedata;
01938
01939
01940 { QDataStream imstr(&internalmovedata, QIODevice::WriteOnly);
01941 imstr.setVersion(QDataStream::Qt_4_4);
01942 imstr << vprop << entryids;
01943 }
01944 mimedata->setData("application/x-klf-internal-lib-move-entries", internalmovedata);
01945
01946 return mimedata;
01947 }
01948
01949
01950 bool KLFLibModel::dropCanInternal(const QMimeData *mimedata)
01951 {
01952 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01953 if ( ! mimedata->hasFormat("application/x-klf-internal-lib-move-entries") ||
01954 ! pResource->canModifyData(KLFLibResourceEngine::ChangeData))
01955 return false;
01956
01957 QByteArray imdata = mimedata->data("application/x-klf-internal-lib-move-entries");
01958 QDataStream imstr(imdata);
01959 imstr.setVersion(QDataStream::Qt_4_4);
01960 QVariantMap vprop;
01961 imstr >> vprop;
01962 QUrl theirurl = vprop.value("Url").toUrl();
01963 QUrl oururl = url();
01964 bool ok = (oururl.toEncoded() == theirurl.toEncoded());
01965 klfDbg( "drag originated from "<<theirurl<<"; we are "<<oururl<<"; OK="<<ok ) ;
01966 return ok;
01967 }
01968
01969 bool KLFLibModel::dropMimeData(const QMimeData *mimedata, Qt::DropAction action, int row,
01970 int column, const QModelIndex& parent)
01971 {
01972 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
01973 klfDbg( "Drop data: action="<<action<<" row="<<row<<" col="<<column
01974 << " parent="<<parent ) ;
01975
01976 if (action == Qt::IgnoreAction)
01977 return true;
01978 if (action != Qt::CopyAction)
01979 return false;
01980
01981 if ( ! (mimedata->hasFormat("application/x-klf-internal-lib-move-entries") &&
01982 pResource->canModifyData(KLFLibResourceEngine::ChangeData)) &&
01983 ! (KLFAbstractLibEntryMimeEncoder::canDecodeMimeData(mimedata) &&
01984 pResource->canModifyData(KLFLibResourceEngine::InsertData)) ) {
01985
01986
01987 return false;
01988 }
01989
01990 if (column > 0)
01991 return false;
01992
01993
01994 bool useinternalmove = dropCanInternal(mimedata);
01995 if (useinternalmove) {
01996 klfDbg( "Dropping application/x-klf-internal-lib-move-entries" ) ;
01997 if ( !(pFlavorFlags & CategoryTree) )
01998 return false;
01999
02000 QByteArray imdata = mimedata->data("application/x-klf-internal-lib-move-entries");
02001 QDataStream imstr(imdata);
02002 imstr.setVersion(QDataStream::Qt_4_4);
02003 QList<KLFLib::entryId> idlist;
02004 QVariantMap vprop;
02005 imstr >> vprop >> idlist;
02006
02007 KLFLibModelCache::NodeId pn = pCache->getNodeForIndex(parent);
02008 if (!pn.valid()) {
02009 pn = KLFLibModelCache::NodeId::rootNode();
02010 }
02011 if (ItemKind(pn.kind) != CategoryLabelKind) {
02012 qWarning()<<"Dropped in a non-category index! (kind="<<pn.kind<<")";
02013 return false;
02014 }
02015 const KLFLibModelCache::CategoryLabelNode& cn = pCache->getCategoryLabelNodeRef(pn);
02016
02017 QString newcategory = cn.fullCategoryPath;
02018 if (newcategory.endsWith("/"))
02019 newcategory.chop(1);
02020
02021 bool r = pResource->changeEntries(idlist, QList<int>() << KLFLibEntry::Category,
02022 QList<QVariant>() << QVariant(newcategory));
02023 klfDbg( "Accepted drop of type application/x-klf-internal-lib-move-entries. Res="<<r<<"\n"
02024 <<"ID list is "<<idlist<<" new category is "<<newcategory ) ;
02025 if (!r) {
02026 return false;
02027 }
02028
02029 return true;
02030 }
02031
02032 klfDbg( "Dropping entry list." ) ;
02033
02034 KLFLibEntryList elist;
02035 QVariantMap vprop;
02036 bool res = KLFAbstractLibEntryMimeEncoder::decodeMimeData(mimedata, &elist, &vprop);
02037 if ( ! res ) {
02038 qWarning()<<KLF_FUNC_NAME<<": Drop: Can't decode mime data! provided types="
02039 <<mimedata->formats();
02040 QMessageBox::warning(NULL, tr("Drop Error", "[[message box title]]"),
02041 tr("Error dropping data."));
02042 return false;
02043 }
02044
02045 if ( elist.isEmpty() )
02046 return true;
02047
02048
02049 QList<KLFLib::entryId> inserted = pResource->insertEntries(elist);
02050 res = (inserted.size() && !inserted.contains(-1));
02051 klfDbg( "Dropped entry list "<<elist<<". Originating URL="
02052 <<(vprop.contains("Url")?vprop["Url"]:"(none)")<<". result="<<res ) ;
02053 if (!res)
02054 return false;
02055
02056
02057 return true;
02058 }
02059
02060 uint KLFLibModel::dropFlags(QDragMoveEvent *event, QAbstractItemView *view)
02061 {
02062 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02063 const QMimeData *mdata = event->mimeData();
02064 if (dropCanInternal(mdata)) {
02065 if ( !(pFlavorFlags & CategoryTree) ) {
02066 return 0;
02067
02068 }
02069
02070 QModelIndex dropOnIndex = view->indexAt(event->pos());
02071 if (pResource->canModifyData(KLFLibResourceEngine::ChangeData) &&
02072 (!dropOnIndex.isValid() || dropOnIndex.column() == 0) )
02073 return DropWillAccept|DropWillMove|DropWillCategorize;
02074 return 0;
02075 }
02076 if (KLFAbstractLibEntryMimeEncoder::canDecodeMimeData(mdata) &&
02077 pResource->canModifyData(KLFLibResourceEngine::InsertData))
02078 return DropWillAccept;
02079 return 0;
02080 }
02081
02082 QImage KLFLibModel::dragImage(const QModelIndexList& indexes)
02083 {
02084 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02085 if (indexes.isEmpty())
02086 return QImage();
02087
02088 const int MAX = 5;
02089 const QSize s1 = 0.8*QSize(250,75);
02090 const QPointF delta(18.0, 20.0);
02091 QList<QImage> previewlist;
02092 QList<KLFLibModelCache::NodeId> alreadydone;
02093 int k, j;
02094 int iS = indexes.size();
02095 int n = qMin(1+MAX, iS);
02096 for (j = 0, k = 0; k < iS && j < n; ++k) {
02097 KLFLibModelCache::NodeId n = pCache->getNodeForIndex(indexes[iS-k-1]);
02098 if (!n.valid() || n.kind != KLFLibModelCache::EntryKind)
02099 continue;
02100 if (alreadydone.contains(n))
02101 continue;
02102 const KLFLibModelCache::EntryNode& en = pCache->getEntryNodeRef(n, true);
02103 alreadydone << n;
02104 previewlist << en.entry.preview().scaled(s1, Qt::KeepAspectRatio, Qt::SmoothTransformation);
02105 ++j;
02106 }
02107 if (previewlist.isEmpty())
02108 return QImage();
02109
02110 int N = qMin(MAX, previewlist.size());
02111 QSize s2 = (s1 + (N-1)*pointToSizeF(delta)).toSize();
02112 QImage image(s2, QImage::Format_ARGB32_Premultiplied);
02113 image.fill(qRgba(0,0,0,0));
02114 {
02115 QPainter p(&image);
02116 QPointF P(0,0);
02117 QPointF lastimgbr;
02118 for (k = 0; k < N; ++k) {
02119
02120 QImage i = transparentify_image(previewlist[k], 0.7);
02121 p.drawImage(P, i);
02122
02123 lastimgbr = P+sizeToPointF(i.size());
02124 P += delta;
02125 }
02126 if (k == MAX) {
02127 p.setCompositionMode(QPainter::CompositionMode_DestinationOver);
02128 p.setPen(QPen(QColor(0,0,0),2.0));
02129 QPointF br = lastimgbr;
02130 p.drawPoint(br - QPointF(5,5));
02131 p.drawPoint(br - QPointF(10,5));
02132 p.drawPoint(br - QPointF(15,5));
02133 }
02134 }
02135
02136 return autocrop_image(image);
02137 }
02138
02139
02140 bool KLFLibModel::isDesendantOf(const QModelIndex& child, const QModelIndex& ancestor)
02141 {
02142 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02143 if (!child.isValid())
02144 return false;
02145
02146 return child.parent() == ancestor || isDesendantOf(child.parent(), ancestor);
02147 }
02148
02149 QStringList KLFLibModel::categoryList() const
02150 {
02151 return pCache->categoryListCache();
02152 }
02153
02154 void KLFLibModel::updateData(const QList<KLFLib::entryId>& entryIdList, int modifyType)
02155 {
02156 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02157 pCache->updateData(entryIdList, modifyType);
02158 }
02159
02160 QModelIndex KLFLibModel::walkNextIndex(const QModelIndex& cur)
02161 {
02162 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02163 KLFLibModelCache::NodeId nextnode = pCache->nextNode(pCache->getNodeForIndex(cur));
02164
02165 return pCache->createIndexFromId(nextnode, -1, 0);
02166 }
02167 QModelIndex KLFLibModel::walkPrevIndex(const QModelIndex& cur)
02168 {
02169 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02170 KLFLibModelCache::NodeId prevnode = pCache->prevNode(pCache->getNodeForIndex(cur));
02171 return pCache->createIndexFromId(prevnode, -1, 0);
02172 }
02173
02174 KLFLib::entryId KLFLibModel::entryIdForIndex(const QModelIndex& index) const
02175 {
02176 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02177 return entryIdForIndexList(QModelIndexList() << index) [0];
02178 }
02179
02180 QModelIndex KLFLibModel::findEntryId(KLFLib::entryId eid) const
02181 {
02182 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02183 return findEntryIdList(QList<KLFLib::entryId>() << eid) [0];
02184 }
02185
02186 QList<KLFLib::entryId> KLFLibModel::entryIdForIndexList(const QModelIndexList& indexlist) const
02187 {
02188 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02189 return pCache->entryIdForIndexList(indexlist);
02190 }
02191 QModelIndexList KLFLibModel::findEntryIdList(const QList<KLFLib::entryId>& eidlist) const
02192 {
02193 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02194 return pCache->findEntryIdList(eidlist);
02195 }
02196
02197
02198 void KLFLibModel::setEntrySorter(KLFLibEntrySorter *entrySorter)
02199 {
02200 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02201 if (pEntrySorter == entrySorter)
02202 return;
02203 if (entrySorter == NULL) {
02204 qWarning()<<KLF_FUNC_NAME<<": NULL entrySorter given!";
02205 }
02206
02207 if (pEntrySorter)
02208 delete pEntrySorter;
02209 pEntrySorter = entrySorter;
02210 }
02211
02212
02213 QModelIndex KLFLibModel::searchFind(const QString& queryString, const QModelIndex& fromIndex,
02214 bool forward)
02215 {
02216 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02217 klfDbg( " s="<<queryString<<" from "<<fromIndex<<" forward="<<forward ) ;
02218 pSearchAborted = false;
02219 pSearchString = queryString;
02220 pSearchCurNode = fromIndex;
02221 return searchFindNext(forward);
02222 }
02223 QModelIndex KLFLibModel::searchFindNext(bool forward)
02224 {
02225 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02226 pSearchAborted = false;
02227 if (pSearchString.isEmpty())
02228 return QModelIndex();
02229
02230 QTime t;
02231
02232 KLFLibModelCache::NodeId curNode = pCache->getNodeForIndex(pSearchCurNode);
02233
02234
02235 KLFLibModelCache::NodeId (KLFLibModelCache::*stepfunc)(KLFLibModelCache::NodeId) =
02236 forward
02237 ? &KLFLibModelCache::nextNode
02238 : &KLFLibModelCache::prevNode;
02239
02240
02241 Qt::CaseSensitivity cs = Qt::CaseInsensitive;
02242 if (pSearchString.contains(QRegExp("[A-Z]")))
02243 cs = Qt::CaseSensitive;
02244
02245 bool found = false;
02246 while ( ! found &&
02247 (curNode = (pCache->*stepfunc)(curNode)).valid() ) {
02248 if ( pCache->searchNodeMatches(curNode, pSearchString, cs) ) {
02249 found = true;
02250 }
02251 if (t.elapsed() > 150) {
02252 pSearchCurNode = pCache->createIndexFromId(curNode, -1, 0);
02253 qApp->processEvents();
02254 if (pSearchAborted)
02255 break;
02256 t.restart();
02257 }
02258 }
02259 pSearchCurNode = pCache->createIndexFromId(curNode, -1, 0);
02260 if (found) {
02261 klfDbg( "found "<<pSearchString<<" at "<<pSearchCurNode ) ;
02262 return pSearchCurNode;
02263 }
02264 return QModelIndex();
02265 }
02266
02267 void KLFLibModel::searchAbort()
02268 {
02269 pSearchAborted = true;
02270 }
02271
02272 bool KLFLibModelCache::searchNodeMatches(const NodeId& nodeId, const QString& searchString,
02273 Qt::CaseSensitivity cs)
02274 {
02275 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02276 if (nodeId.kind == CategoryLabelKind) {
02277 if (nodeValue(nodeId).contains(searchString, cs))
02278 return true;
02279 return false;
02280 }
02281 if (nodeValue(nodeId, KLFLibEntry::Latex).contains(searchString, cs) ||
02282 nodeValue(nodeId, KLFLibEntry::Tags).contains(searchString, cs))
02283 return true;
02284
02285
02286 if ((pModel->pFlavorFlags & KLFLibModel::CategoryTree) == 0 &&
02287 nodeValue(nodeId, KLFLibEntry::Category).contains(searchString, cs)) {
02288 return true;
02289 }
02290
02291 return false;
02292 }
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314
02315
02316
02317
02318
02319
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341 void KLFLibModel::completeRefresh()
02342 {
02343 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02344 updateCacheSetupModel();
02345 }
02346
02347
02348 void KLFLibModel::redoSort()
02349 {
02350 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02351
02352
02353 updateCacheSetupModel();
02354 return;
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366 }
02367
02368 void KLFLibModel::sort(int column, Qt::SortOrder order)
02369 {
02370 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02371
02372
02373 int propId = entryColumnContentsPropertyId(column);
02374
02375 if (propId == KLFLibEntry::Preview) {
02376 propId = KLFLibEntry::DateTime;
02377 }
02378
02379 pEntrySorter->setPropId(propId);
02380 pEntrySorter->setOrder(order);
02381
02382 pCache->setSortingBy(propId, order);
02383
02384 redoSort();
02385 }
02386
02387
02388
02389 QList<KLFLibModel::PersistentId> KLFLibModel::persistentIdList(const QModelIndexList& persistentIndexes)
02390 {
02391 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02392
02393 QList<PersistentId> persistentIndexIds;
02394 int k;
02395 for (k = 0; k < persistentIndexes.size(); ++k) {
02396 PersistentId id;
02397 KLFLibModelCache::NodeId n = pCache->getNodeForIndex(persistentIndexes[k]);
02398 if (!n.valid()) {
02399 id.kind = (ItemKind)-1;
02400 } else {
02401 id.kind = n.kind;
02402 if (ItemKind(id.kind) == EntryKind)
02403 id.entry_id = pCache->getEntryNodeRef(n).entryid;
02404 else if (ItemKind(id.kind) == CategoryLabelKind)
02405 id.categorylabel_fullpath = pCache->getCategoryLabelNodeRef(n).fullCategoryPath;
02406 else
02407 qWarning("KLFLibModel::persistentIdList: Bad Node kind: %d!!", id.kind);
02408 }
02409 id.column = persistentIndexes[k].column();
02410 persistentIndexIds << id;
02411 klfDbg("saved persistent id "<<id) ;
02412 }
02413 return persistentIndexIds;
02414 }
02415 QModelIndexList KLFLibModel::newPersistentIndexList(const QList<PersistentId>& persistentIndexIds)
02416 {
02417 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02418 QModelIndexList newPersistentIndexes;
02419 int k;
02420 for (k = 0; k < persistentIndexIds.size(); ++k) {
02421
02422 PersistentId id = persistentIndexIds[k];
02423 QModelIndex index;
02424 if (ItemKind(id.kind) == EntryKind) {
02425 QModelIndexList ilist = pCache->findEntryIdList(QList<KLFLib::entryId>() << id.entry_id);
02426 index = ilist[0];
02427 } else if (id.kind == CategoryLabelKind) {
02428 int idx = pCache->cacheFindCategoryLabel(id.categorylabel_fullpath.split('/'));
02429 KLFLibModelCache::NodeId nodeId(KLFLibModelCache::CategoryLabelKind, idx);
02430 index = pCache->createIndexFromId(nodeId, -1, 0);
02431 } else {
02432 qWarning("%s: bad persistent id node kind! :%d", KLF_FUNC_NAME, id.kind);
02433 }
02434
02435 newPersistentIndexes << index;
02436 klfDbg("restoring persistent id "<<id<<" as index "<<index) ;
02437 }
02438 return newPersistentIndexes;
02439 }
02440
02441
02442 void KLFLibModel::startLayoutChange(bool withQtLayoutChangedSignal)
02443 {
02444 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02445
02446 if (withQtLayoutChangedSignal)
02447 emit layoutAboutToBeChanged();
02448
02449 pLytChgIndexes = persistentIndexList();
02450 pLytChgIds = persistentIdList(pLytChgIndexes);
02451 }
02452 void KLFLibModel::endLayoutChange(bool withQtLayoutChangedSignal)
02453 {
02454 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
02455
02456 QModelIndexList newpindexes = newPersistentIndexList(pLytChgIds);
02457 changePersistentIndexList(pLytChgIndexes, newpindexes);
02458
02459 if (withQtLayoutChangedSignal)
02460 emit layoutChanged();
02461 }
02462
02463
02464 void KLFLibModel::updateCacheSetupModel()
02465 {
02466 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02467 pCache->rebuildCache();
02468 }
02469
02470
02471
02472
02473
02474
02475 KLFLibViewDelegate::KLFLibViewDelegate(QObject *parent)
02476 : QAbstractItemDelegate(parent), pSelModel(NULL), pTheTreeView(NULL),
02477 pPreviewSize(klfconfig.UI.labelOutputFixedSize)
02478 {
02479 pAutoBackgroundItems = true;
02480 }
02481 KLFLibViewDelegate::~KLFLibViewDelegate()
02482 {
02483 }
02484
02485 QWidget * KLFLibViewDelegate::createEditor(QWidget *,
02486 const QStyleOptionViewItem& ,
02487 const QModelIndex& ) const
02488 {
02489 return 0;
02490 }
02491 bool KLFLibViewDelegate::editorEvent(QEvent *, QAbstractItemModel *,
02492 const QStyleOptionViewItem& ,
02493 const QModelIndex& )
02494 {
02495 return false;
02496 }
02497
02498
02500 class _klf_block_progress_blocker
02501 {
02502 KLFLibResourceEngine *res;
02503 public:
02504 _klf_block_progress_blocker(KLFLibResourceEngine *r) : res(r)
02505 {
02506 if (res != NULL)
02507 res->blockProgressReporting(true);
02508 }
02509 ~_klf_block_progress_blocker()
02510 {
02511 if (res != NULL)
02512 res->blockProgressReporting(false);
02513 }
02514 };
02515
02516
02517 void KLFLibViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem& option,
02518 const QModelIndex& index) const
02519 {
02520 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02521 klfDbg( "\tindex="<<index<<"; rect="<<option.rect ) ;
02522 PaintPrivate pp;
02523 pp.p = painter;
02524 pp.option = &option;
02525 pp.innerRectImage = QRect(option.rect.topLeft()+QPoint(2,2), option.rect.size()-QSize(4,4));
02526 pp.innerRectText = QRect(option.rect.topLeft()+QPoint(4,2), option.rect.size()-QSize(8,3));
02527
02528 #ifdef Q_WS_MAC
02529
02530 KLFLibResourceEngine *rres = NULL;
02531 KLFLibModel *rmodel = qobject_cast<KLFLibModel*>(const_cast<QAbstractItemModel*>(index.model()));
02532 if (rmodel != NULL) rres = rmodel->resource();
02533 _klf_block_progress_blocker blocker(rres);
02534 #endif
02535
02536 painter->save();
02537
02538 QPen pen = painter->pen();
02539 pp.isselected = (option.state & QStyle::State_Selected);
02540 QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
02541 ? QPalette::Normal : QPalette::Disabled;
02542 if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
02543 cg = QPalette::Inactive;
02544 if (pp.isselected) {
02545 pp.background = option.palette.brush(cg, QPalette::Highlight);
02546 painter->setPen(option.palette.color(cg, QPalette::HighlightedText));
02547 painter->fillRect(option.rect, pp.background);
02548 } else {
02549 pp.background = pAutoBackgroundColor.isValid()
02550 ? pAutoBackgroundColor
02551 : option.palette.brush(cg, QPalette::Base);
02552 painter->setPen(option.palette.color(cg, QPalette::Text));
02553 }
02554
02555 int kind = index.data(KLFLibModel::ItemKindItemRole).toInt();
02556 if (kind == KLFLibModel::EntryKind)
02557 paintEntry(&pp, index);
02558 else if (kind == KLFLibModel::CategoryLabelKind)
02559 paintCategoryLabel(&pp, index);
02560
02561 if (option.state & QStyle::State_HasFocus) {
02562 QStyleOptionFocusRect o;
02563 o.QStyleOption::operator=(option);
02564 o.rect = option.rect;
02565 o.state |= QStyle::State_KeyboardFocusChange;
02566 o.state |= QStyle::State_Item;
02567 QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled)
02568 ? QPalette::Normal : QPalette::Disabled;
02569 o.backgroundColor = option.palette.color(cg, (option.state & QStyle::State_Selected)
02570 ? QPalette::Highlight : QPalette::Window);
02571 const QWidget *w = 0;
02572 if (const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3 *>(&option))
02573 w = v3->widget;
02574 QStyle *style = w ? w->style() : QApplication::style();
02575 style->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter, w);
02576 }
02577
02578 painter->restore();
02579 }
02580
02581 void KLFLibViewDelegate::paintEntry(PaintPrivate *p, const QModelIndex& index) const
02582 {
02583 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02584 uint fl = PTF_HighlightSearch;
02585 if (index.parent() == pSearchIndex.parent() && index.row() == pSearchIndex.row())
02586 fl |= PTF_HighlightSearchCurrent;
02587
02588 switch (index.data(KLFLibModel::EntryContentsTypeItemRole).toInt()) {
02589 case KLFLibEntry::Latex:
02590
02591 fl |= PTF_FontTT;
02592 paintText(p, index.data(KLFLibModel::entryItemRole(KLFLibEntry::Latex)).toString(), fl);
02593 break;
02594 case KLFLibEntry::Preview:
02595
02596 {
02597 QImage img = index.data(KLFLibModel::entryItemRole(KLFLibEntry::Preview)).value<QImage>();
02598 QImage img2 = img.scaled(p->innerRectImage.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
02599 if (p->isselected)
02600 img2 = transparentify_image(img2, 0.85);
02601 QPoint pos = p->innerRectImage.topLeft()
02602 + QPoint(0, (p->innerRectImage.height()-img2.height()) / 2);
02603 if (pAutoBackgroundItems) {
02604
02605
02606 klfDbg( " BG Brush is "<<p->background ) ;
02607 QColor bgcolor = p->background.color();
02608 QList<QColor> bglista, bglistb, bglist;
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618 bglist << bgcolor;
02619 bglista = bglistb = bglist;
02620 int count;
02621 for (count = 0; count < 5; ++count)
02622 bglista << bglista.last().darker(105+count*2);
02623 for (count = 0; count < 5; ++count)
02624 bglistb << bglistb.last().lighter(105+count*2);
02625
02626 bglist << bglista.mid(1) << bglistb.mid(1) << QColor(255,255,255) << QColor(0,0,0);
02627 klfDbg( "alt. bg list is "<<bglist );
02628 int k;
02629 for (k = 0; k < bglist.size(); ++k) {
02630
02631
02632 bool distinguishable = image_is_distinguishable(img2, bglist[k], 20);
02633 if ( distinguishable )
02634 break;
02635 }
02636
02637 if (k > 0 && k < bglist.size())
02638 p->p->fillRect(QRect(pos, img2.size()), QBrush(bglist[k]));
02639 }
02640
02641 p->p->save();
02642 p->p->translate(pos);
02643 if (klfconfig.UI.glowEffect)
02644 klfDrawGlowedImage(p->p, img2, klfconfig.UI.glowEffectColor, klfconfig.UI.glowEffectRadius, false);
02645 p->p->drawImage(QPoint(0,0), img2);
02646 p->p->restore();
02647 break;
02648 }
02649 case KLFLibEntry::Category:
02650
02651 paintText(p, index.data(KLFLibModel::entryItemRole(KLFLibEntry::Category)).toString(), fl);
02652 break;
02653 case KLFLibEntry::Tags:
02654
02655 fl |= PTF_FontLarge;
02656 paintText(p, index.data(KLFLibModel::entryItemRole(KLFLibEntry::Tags)).toString(), fl);
02657 break;
02658 case KLFLibEntry::DateTime:
02659
02660 { QLocale loc;
02661 paintText(p, loc.toString(index.data(KLFLibModel::entryItemRole(KLFLibEntry::DateTime))
02662 .toDateTime(), QLocale::LongFormat), fl);
02663 break;
02664 }
02665 default:
02666 qDebug("KLFLibViewDelegate::paintEntry(): Got bad contents type %d !",
02667 index.data(KLFLibModel::EntryContentsTypeItemRole).toInt());
02668
02669
02670 }
02671 }
02672
02673 void KLFLibViewDelegate::paintCategoryLabel(PaintPrivate *p, const QModelIndex& index) const
02674 {
02675 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02676
02677
02678
02679
02680 if (index.column() > 0)
02681 return;
02682
02683
02684
02685 uint fl = PTF_HighlightSearch;
02686 if (index.parent() == pSearchIndex.parent() && index.row() == pSearchIndex.row())
02687 fl |= PTF_HighlightSearchCurrent;
02688 if ( pTheTreeView != NULL && !pTheTreeView->isExpanded(index) &&
02689 indexHasSelectedDescendant(index) ) {
02690 fl |= PTF_SelUnderline;
02691 }
02692
02693
02694
02695
02696
02697 if (fl & PTF_HighlightSearchCurrent) {
02698
02699 QPen pen = p->p->pen();
02700 QPalette::ColorGroup cg = p->option->state & QStyle::State_Enabled
02701 ? QPalette::Normal : QPalette::Disabled;
02702 if (cg == QPalette::Normal && !(p->option->state & QStyle::State_Active))
02703 cg = QPalette::Inactive;
02704 p->p->fillRect(p->option->rect, p->option->palette.brush(cg, QPalette::Highlight));
02705 p->p->setPen(p->option->palette.color(cg, QPalette::HighlightedText));
02706 }
02707
02708
02709 paintText(p, index.data(KLFLibModel::CategoryLabelItemRole).toString(), fl);
02710 }
02711
02712 void KLFLibViewDelegate::paintText(PaintPrivate *p, const QString& text, uint flags) const
02713 {
02714 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02715
02716 QFont font = p->option->font;
02717
02718 if (flags & PTF_FontTT)
02719 font = klfconfig.UI.preambleEditFont;
02720 if (flags & PTF_FontLarge) {
02721 font.setPointSize(QFontInfo(font).pointSize()+1);
02722
02723 }
02724
02725 QColor textcol = p->option->palette.color(QPalette::Text);
02726 QColor textcoltransp = textcol; textcoltransp.setAlpha(0);
02727 QGradientStops borderfadelingrstops;
02728 borderfadelingrstops << QGradientStop(0.0f, textcoltransp)
02729 << QGradientStop(0.1f, textcol)
02730 << QGradientStop(0.9f, textcol)
02731 << QGradientStop(1.0f, textcoltransp);
02732 QLinearGradient borderfadelingr(p->innerRectText.topLeft(), p->innerRectText.bottomLeft());
02733 borderfadelingr.setStops(borderfadelingrstops);
02734 borderfadelingr.setCoordinateMode(QGradient::LogicalMode);
02735 QPen borderfadepen = QPen(QBrush(borderfadelingr), 1.0f);
02736 QPen normalpen = QPen(textcol, 1.0f);
02737
02738 int drawnTextWidth;
02739 int drawnBaseLineY;
02740 if ( (pSearchString.isEmpty() || !(flags&PTF_HighlightSearch) ||
02741 text.indexOf(pSearchString, 0, Qt::CaseInsensitive) == -1) &&
02742 !(flags & PTF_SelUnderline) &&
02743 !(flags & PTF_ForceRichTextRender) ) {
02744
02745 QSize s = QFontMetrics(font).size(0, text);
02746 drawnTextWidth = s.width();
02747 drawnBaseLineY = (int)(p->innerRectText.bottom() - 0.5f*(p->innerRectText.height()-s.height()));
02748 p->p->setFont(font);
02749 if (s.height() > p->innerRectText.height()) {
02750 klfDbg("Need border fade pen for text "<<text) ;
02751 p->p->setPen(borderfadepen);
02752 } else {
02753 klfDbg("Don't need border fade pen for text "<<text) ;
02754 p->p->setPen(normalpen);
02755 }
02756 p->p->drawText(p->innerRectText, Qt::AlignLeft|Qt::AlignVCenter, text);
02757 } else {
02758
02759
02760 QList<ColorRegion> c;
02761 QTextCharFormat f_highlight;
02762 if (flags & PTF_HighlightSearchCurrent)
02763 f_highlight.setBackground(QColor(0,255,0,80));
02764 f_highlight.setForeground(QColor(128,0,0));
02765 f_highlight.setFontItalic(true);
02766 f_highlight.setFontWeight(QFont::Bold);
02767 int i = -1, ci, j;
02768 if (!pSearchString.isEmpty()) {
02769 while ((i = text.indexOf(pSearchString, i+1, Qt::CaseInsensitive)) != -1)
02770 c << ColorRegion(f_highlight, i, pSearchString.length());
02771 }
02772 qSort(c);
02773
02774 QTextDocument textDocument;
02775 textDocument.setDefaultFont(font);
02776 QTextCursor cur(&textDocument);
02777 QList<ColorRegion> appliedfmts;
02778 for (i = ci = 0; i < text.length(); ++i) {
02779
02780 if (ci >= c.size() && appliedfmts.size() == 0) {
02781
02782 cur.insertText(Qt::escape(text.mid(i)), QTextCharFormat());
02783 break;
02784 }
02785 while (ci < c.size() && c[ci].start == i) {
02786 appliedfmts.append(c[ci]);
02787 ++ci;
02788 }
02789 QTextCharFormat f;
02790 for (j = 0; j < appliedfmts.size(); ++j) {
02791 if (i >= appliedfmts[j].start + appliedfmts[j].len) {
02792
02793 appliedfmts.removeAt(j);
02794 --j;
02795 continue;
02796 }
02797 f.merge(appliedfmts[j].fmt);
02798 }
02799 cur.insertText(Qt::escape(text[i]), f);
02800 }
02801
02802 QSizeF s = textDocument.size();
02803 QRectF textRect = p->innerRectText;
02804
02805 textRect.setLeft(textRect.left()-4);
02806
02807
02808 if (flags & PTF_SelUnderline) {
02809 QColor h1 = p->option->palette.color(QPalette::Highlight);
02810 QColor h2 = h1;
02811 h1.setAlpha(0);
02812 h2.setAlpha(220);
02813 QLinearGradient gr(0.f, 0.f, 0.f, 1.f);
02814 gr.setCoordinateMode(QGradient::ObjectBoundingMode);
02815 gr.setColorAt(0.f, h1);
02816 gr.setColorAt(1.f, h2);
02817 QBrush selbrush(gr);
02818 p->p->save();
02819
02820 p->p->fillRect(QRectF(textRect.left(), textRect.bottom()-10,
02821 textRect.width(), 10), selbrush);
02822 p->p->restore();
02823 }
02824
02825 drawnTextWidth = (int)s.width();
02826 if (s.width() > textRect.width()) {
02827 s.setWidth(textRect.width());
02828 }
02829 p->p->save();
02830 p->p->setClipRect(textRect);
02831 if (s.height() > textRect.height()) {
02832 klfDbg("Need borderfadepen for (rich) text "<<textDocument.toHtml());
02833 p->p->setPen(borderfadepen);
02834 } else {
02835 p->p->setPen(normalpen);
02836 }
02837 p->p->translate(textRect.topLeft());
02838 p->p->translate( QPointF( 0,
02839 textRect.height() - s.height()) / 2.f );
02840 textDocument.drawContents(p->p);
02841 p->p->restore();
02842 drawnBaseLineY = (int)(textRect.bottom() - (textRect.height() - s.height()) / 2.f);
02843 }
02844
02845
02846
02847 if (drawnTextWidth > p->innerRectText.width()) {
02848
02849
02850 p->p->save();
02851 p->p->translate(p->option->rect.right()-2, drawnBaseLineY-2);
02852 p->p->setPen(textcol);
02853 p->p->drawLine(0, 0, -16, 0);
02854 p->p->drawLine(0, 0, -2, +2);
02855 p->p->restore();
02856 }
02857 }
02858
02859 void KLFLibViewDelegate::setEditorData(QWidget *, const QModelIndex& ) const
02860 {
02861 }
02862 void KLFLibViewDelegate::setModelData(QWidget *, QAbstractItemModel *,
02863 const QModelIndex& ) const
02864 {
02865 }
02866 QSize KLFLibViewDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
02867 {
02868 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02869 klfDbg( "\tindex="<<index ) ;
02870 int kind = index.data(KLFLibModel::ItemKindItemRole).toInt();
02871 if (kind == KLFLibModel::EntryKind) {
02872 int prop = -1;
02873 switch (index.data(KLFLibModel::EntryContentsTypeItemRole).toInt()) {
02874 case KLFLibEntry::Latex: prop = KLFLibEntry::Latex;
02875 case KLFLibEntry::Category: prop = (prop > 0) ? prop : KLFLibEntry::Category;
02876 case KLFLibEntry::Tags: prop = (prop > 0) ? prop : KLFLibEntry::Tags;
02877 return QFontMetrics(option.font)
02878 .size(0, index.data(KLFLibModel::entryItemRole(prop)).toString())+QSize(4,4);
02879 case KLFLibEntry::DateTime:
02880 { QLocale loc;
02881 return QFontMetrics(option.font)
02882 .size(0, loc.toString(index.data(KLFLibModel::entryItemRole(KLFLibEntry::DateTime))
02883 .toDateTime(), QLocale::LongFormat) )+QSize(4,2);
02884 }
02885 case KLFLibEntry::Preview:
02886 {
02887 QSize s = index.data(KLFLibModel::entryItemRole(KLFLibEntry::PreviewSize)).value<QSize>() + QSize(4,3);
02888 if (s.width() > pPreviewSize.width() || s.height() > pPreviewSize.height()) {
02889
02890 s.scale(pPreviewSize, Qt::KeepAspectRatio);
02891 }
02892 return s+QSize(2,2);
02893 }
02894 default:
02895 return QSize();
02896 }
02897 } else if (kind == KLFLibModel::CategoryLabelKind) {
02898 return QFontMetrics(option.font)
02899 .size(0, index.data(KLFLibModel::CategoryLabelItemRole).toString())+QSize(4,4);
02900 } else {
02901 qWarning("KLFLibItemViewDelegate::sizeHint(): Bad Item kind: %d\n", kind);
02902 return QSize();
02903 }
02904 }
02905 void KLFLibViewDelegate::updateEditorGeometry(QWidget *,
02906 const QStyleOptionViewItem& ,
02907 const QModelIndex& ) const
02908 {
02909 }
02910
02911
02912 bool KLFLibViewDelegate::indexHasSelectedDescendant(const QModelIndex& parent) const
02913 {
02914 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02915 klfDbg( "\t parent="<<parent ) ;
02916
02917 if (!parent.isValid())
02918 return false;
02919
02920 QTime tm; tm.start();
02921 return func_indexHasSelectedDescendant(parent, tm, 200);
02922 }
02923
02924 bool KLFLibViewDelegate::selectionIntersectsIndexChildren(const QItemSelection& selection,
02925 const QModelIndex& parent) const
02926 {
02927 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02928 klfDbg( "selection size is "<<selection.size() ) ;
02929 int k;
02930 for (k = 0; k < selection.size(); ++k) {
02931 if (selection[k].parent() != parent)
02932 continue;
02933 if (selection[k].isValid())
02934 return true;
02935 }
02936 return false;
02937 }
02938
02939 bool KLFLibViewDelegate::func_indexHasSelectedDescendant(const QModelIndex& parent, const QTime& timer,
02940 int timeLimitMs) const
02941 {
02942 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02943 if (!parent.isValid()) {
02944 qWarning()<<KLF_FUNC_NAME<<": parent is invalid!";
02945 return false;
02946 }
02947 if (selectionIntersectsIndexChildren(pSelModel->selection(), parent)) {
02948 klfDbg( "selection under index parent="<<parent ) ;
02949 return true;
02950 }
02951 const QAbstractItemModel *model = parent.model();
02952 if (model == NULL) {
02953 qWarning()<<KLF_FUNC_NAME<<": parent has NULL model!";
02954 return false;
02955 }
02956
02957 int k;
02958 QModelIndex idx;
02959 for (k = 0; k < model->rowCount(parent); ++k) {
02960 idx = model->index(k, 0, parent);
02961
02962 if (!idx.isValid() || !model->hasChildren(idx))
02963 continue;
02964 if (func_indexHasSelectedDescendant(idx, timer, timeLimitMs))
02965 return true;
02966
02967 if (timer.elapsed() > timeLimitMs)
02968 return false;
02969
02970 }
02971 return false;
02972 }
02973
02974
02975
02976
02977
02978
02979
02980
02981 KLFLibDefaultView::KLFLibDefaultView(QWidget *parent, ViewType view)
02982 : KLFAbstractLibView(parent), pViewType(view)
02983 {
02984 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
02985
02986 pModel = NULL;
02987
02988 pPreviewSizeMenu = NULL;
02989
02990 pEventFilterNoRecurse = false;
02991
02992 QVBoxLayout *lyt = new QVBoxLayout(this);
02993 lyt->setMargin(0);
02994 lyt->setSpacing(0);
02995 pDelegate = new KLFLibViewDelegate(this);
02996
02997
02998 switch (pViewType) {
02999 case CategoryTreeView:
03000 pDelegate->setPreviewSize(klfconfig.UI.labelOutputFixedSize*klfconfig.LibraryBrowser.treePreviewSizePercent/100.0);
03001 break;
03002 case ListTreeView:
03003 pDelegate->setPreviewSize(klfconfig.UI.labelOutputFixedSize*klfconfig.LibraryBrowser.listPreviewSizePercent/100.0);
03004 break;
03005 case IconView:
03006 pDelegate->setPreviewSize(klfconfig.UI.labelOutputFixedSize*klfconfig.LibraryBrowser.iconPreviewSizePercent/100.0);
03007 break;
03008 default:
03009 break;
03010 }
03011
03012 setFocusPolicy(Qt::NoFocus);
03013
03014 KLFLibDefTreeView *treeView = NULL;
03015 KLFLibDefListView *listView = NULL;
03016 switch (pViewType) {
03017 case IconView:
03018 listView = new KLFLibDefListView(this);
03019 klfDbg( "Created list view." ) ;
03020 listView->setViewMode(QListView::IconMode);
03021 listView->setSpacing(15);
03022 listView->setMovement(QListView::Free);
03023
03024 listView->setResizeMode(QListView::Adjust);
03025 klfDbg( "prepared list view." ) ;
03026 pView = listView;
03027 break;
03028 case CategoryTreeView:
03029 case ListTreeView:
03030 default:
03031 treeView = new KLFLibDefTreeView(this);
03032 treeView->setSortingEnabled(true);
03033 treeView->setIndentation(16);
03034 treeView->setAllColumnsShowFocus(true);
03035
03036 pDelegate->setTheTreeView(treeView);
03037 pView = treeView;
03038 break;
03039 };
03040
03041 lyt->addWidget(pView);
03042
03043
03044 pView->setSelectionBehavior(QAbstractItemView::SelectRows);
03045 pView->setSelectionMode(QAbstractItemView::ExtendedSelection);
03046 pView->setDragEnabled(true);
03047 pView->setDragDropMode(QAbstractItemView::DragDrop);
03048 pView->setDragDropOverwriteMode(false);
03049 pView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
03050 pView->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
03051 pView->setItemDelegate(pDelegate);
03052 pView->viewport()->installEventFilter(this);
03053 pView->installEventFilter(this);
03054 installEventFilter(this);
03055
03056 connect(pView, SIGNAL(clicked(const QModelIndex&)),
03057 this, SLOT(slotViewItemClicked(const QModelIndex&)));
03058 connect(pView, SIGNAL(doubleClicked(const QModelIndex&)),
03059 this, SLOT(slotEntryDoubleClicked(const QModelIndex&)));
03060 }
03061 KLFLibDefaultView::~KLFLibDefaultView()
03062 {
03063 }
03064
03065 QUrl KLFLibDefaultView::url() const
03066 {
03067 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
03068
03069 if (pModel == NULL)
03070 return QUrl();
03071 return pModel->url();
03072 }
03073 uint KLFLibDefaultView::compareUrlTo(const QUrl& other, uint interestFlags) const
03074 {
03075 bool baseequal = false;
03076 uint resultFlags = 0x0;
03077
03078
03079 baseequal = resourceEngine()->compareUrlTo(other, KlfUrlCompareBaseEqual);
03080 if (baseequal)
03081 resultFlags |= KlfUrlCompareBaseEqual;
03082
03083
03084 if (interestFlags & KlfUrlCompareLessSpecific) {
03085 if (!baseequal) {
03086
03087 } else {
03088
03089
03090
03091 if ( ! (resourceEngine()->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResources) ) {
03092 resultFlags |= KlfUrlCompareLessSpecific;
03093 } else if (other.hasQueryItem("klfDefaultSubResource")) {
03094 if (resourceEngine()->compareDefaultSubResourceEquals(other.queryItemValue("klfDefaultSubResource")))
03095 resultFlags |= KlfUrlCompareLessSpecific;
03096 }
03097 }
03098 }
03099 if (interestFlags & KlfUrlCompareMoreSpecific) {
03100 if (!baseequal) {
03101
03102 } else {
03103
03104
03105
03106
03107 if (!other.hasQueryItem("klfDefaultSubResource")) {
03108 resultFlags |= KlfUrlCompareMoreSpecific;
03109 } else if (! (resourceEngine()->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResources)) {
03110
03111 } else {
03112
03113 if (resourceEngine()->compareDefaultSubResourceEquals(other.queryItemValue("klfDefaultSubResource")))
03114 resultFlags |= KlfUrlCompareMoreSpecific;
03115 }
03116 }
03117 }
03118 if (interestFlags & KlfUrlCompareEqual) {
03119 bool wesupportsubres = (resourceEngine()->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResources);
03120 bool hesupportssubres = other.hasQueryItem("klfDefaultSubResource");
03121 if ( wesupportsubres && hesupportssubres ) {
03122
03123 if (baseequal && resourceEngine()->compareDefaultSubResourceEquals(other.queryItemValue("klfDefaultSubResource")))
03124 resultFlags |= KlfUrlCompareEqual;
03125 } else if ( !wesupportsubres && ! hesupportssubres ) {
03126
03127 resultFlags |= KlfUrlCompareEqual;
03128 } else {
03129
03130 }
03131 }
03132
03133 klfDbg( "and the final resultFlags are"<<klfFmtCC("%#010x",resultFlags) ) ;
03134
03135 return resultFlags;
03136 }
03137
03138 class __klf_guarded_bool {
03139 bool *x;
03140 public:
03141 __klf_guarded_bool(bool *var) : x(var) { *x = true; }
03142 ~__klf_guarded_bool() { *x = false; }
03143 };
03144
03145 bool KLFLibDefaultView::event(QEvent *event)
03146 {
03147 return KLFAbstractLibView::event(event);
03148 }
03149 bool KLFLibDefaultView::eventFilter(QObject *object, QEvent *event)
03150 {
03151 if (pEventFilterNoRecurse) {
03152 klfDbg("Avoiding recursion") ;
03153 return KLFAbstractLibView::eventFilter(object, event);
03154 }
03155 __klf_guarded_bool guard_object(&pEventFilterNoRecurse);
03156
03157 if (object == pView && event->type() == QEvent::KeyPress) {
03158 QKeyEvent *ke = (QKeyEvent*)event;
03159 QKeySequence thisKey = QKeySequence(ke->key() | ke->modifiers());
03160 int k;
03161 for (k = 0; k < pViewActionsWithShortcut.size(); ++k) {
03162 QAction *a = pViewActionsWithShortcut[k];
03163 if (a->shortcut() == thisKey) {
03164 klfDbg("Activating view action "<<a->text()<<" for shortcut key "<<thisKey<<".") ;
03165 a->trigger();
03166 return true;
03167 }
03168 }
03169 }
03170 return KLFAbstractLibView::eventFilter(object, event);
03171 }
03172
03173 QList<KLFLib::entryId> KLFLibDefaultView::selectedEntryIds() const
03174 {
03175 QList<KLFLib::entryId> idListWithDupl = pModel->entryIdForIndexList(pView->selectionModel()->selectedIndexes());
03176
03177 QList<KLFLib::entryId> idList;
03178 int k;
03179 for (k = 0; k < idListWithDupl.size(); ++k) {
03180 if (!idList.contains(idListWithDupl[k]))
03181 idList << idListWithDupl[k];
03182 }
03183 return idList;
03184 }
03185
03186 KLFLibEntryList KLFLibDefaultView::selectedEntries() const
03187 {
03188 QModelIndexList selectedindexes = selectedEntryIndexes();
03189 KLFLibEntryList elist;
03190
03191 int k;
03192 for (k = 0; k < selectedindexes.size(); ++k) {
03193 if ( selectedindexes[k].data(KLFLibModel::ItemKindItemRole) != KLFLibModel::EntryKind )
03194 continue;
03195 KLFLibEntry entry = selectedindexes[k].data(KLFLibModel::FullEntryItemRole).value<KLFLibEntry>();
03196 klfDbg( "selection list: adding item [latex="<<entry.latex()<<"; tags="<<entry.tags()<<"]" ) ;
03197 elist << entry;
03198 }
03199 return elist;
03200 }
03201
03202 QList<QAction*> KLFLibDefaultView::addContextMenuActions(const QPoint& )
03203 {
03204 QList<QAction*> actionList = QList<QAction*>() << pCommonActions;
03205 if (pViewType == IconView) {
03206 actionList << pIconViewActions;
03207 }
03208 if (pViewType == CategoryTreeView || pViewType == ListTreeView) {
03209 actionList << pShowColumnActions;
03210 }
03211 return actionList;
03212 }
03213
03214
03215 QVariantMap KLFLibDefaultView::saveGuiState() const
03216 {
03217 QVariantMap vst;
03218 if (pViewType == CategoryTreeView || pViewType == ListTreeView) {
03219 QTreeView *tv = qobject_cast<QTreeView*>(pView);
03220 KLF_ASSERT_NOT_NULL( tv, "Tree View is NULL in view type "<<pViewType<<" !!", return QVariantMap() )
03221 ;
03222 vst["ColumnsState"] = QVariant::fromValue<QByteArray>(tv->header()->saveState());
03223 }
03224 if (pViewType == IconView) {
03225
03226 }
03227 vst["IconPreviewSize"] = QVariant::fromValue<QSize>(previewSize());
03228 return vst;
03229 }
03230 bool KLFLibDefaultView::restoreGuiState(const QVariantMap& vstate)
03231 {
03232 if (pViewType == CategoryTreeView || pViewType == ListTreeView) {
03233 QByteArray colstate = vstate["ColumnsState"].toByteArray();
03234 QTreeView *tv = qobject_cast<QTreeView*>(pView);
03235 KLF_ASSERT_NOT_NULL( tv, "Tree View is NULL in view type"<<pViewType<<"!!", return false )
03236 ;
03237 tv->header()->restoreState(colstate);
03238 }
03239 if (pViewType == IconView) {
03240
03241 }
03242 setPreviewSize(vstate["IconPreviewSize"].value<QSize>());
03243 return true;
03244 }
03245
03246 QModelIndex KLFLibDefaultView::currentVisibleIndex(bool forward) const
03247 {
03248 QModelIndex index;
03249 if (pViewType == IconView) {
03250 KLFLibDefListView *lv = qobject_cast<KLFLibDefListView*>(pView);
03251 KLF_ASSERT_NOT_NULL( lv, "KLFLibDefListView List View is NULL in view type "<<pViewType<<" !!",
03252 return QModelIndex() )
03253 ;
03254 index = lv->curVisibleIndex(forward);
03255 } else if (pViewType == CategoryTreeView || pViewType == ListTreeView) {
03256 KLFLibDefTreeView *tv = qobject_cast<KLFLibDefTreeView*>(pView);
03257 KLF_ASSERT_NOT_NULL( tv, "KLFLibDefTreeView List View is NULL in view type "<<pViewType<<" !!",
03258 return QModelIndex() )
03259 ;
03260 index = tv->curVisibleIndex(forward);
03261 } else {
03262 index = QModelIndex();
03263 }
03264 return index;
03265 }
03266
03267
03268 #ifdef KLF_DEBUG_USE_MODELTEST
03269 #include <modeltest.h>
03270 #endif
03271
03272 void KLFLibDefaultView::updateResourceEngine()
03273 {
03274 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
03275
03276 int k;
03277 KLFLibResourceEngine *resource = resourceEngine();
03278 if (resource == NULL) {
03279 pModel = NULL;
03280 pView->setModel(NULL);
03281 for (k = 0; k < pShowColumnActions.size(); ++k)
03282 delete pShowColumnActions[k];
03283 pShowColumnActions.clear();
03284 }
03285
03286
03287 uint model_flavor = 0;
03288 switch (pViewType) {
03289 case IconView:
03290 case ListTreeView:
03291 model_flavor = KLFLibModel::LinearList;
03292 break;
03293 case CategoryTreeView:
03294 default:
03295 model_flavor = KLFLibModel::CategoryTree;
03296 break;
03297 };
03298
03299
03300 setGroupSubCategories(klfconfig.LibraryBrowser.groupSubCategories);
03301
03302 if (pGroupSubCategories)
03303 model_flavor |= KLFLibModel::GroupSubCategories;
03304
03305 pModel = new KLFLibModel(resource, model_flavor, this);
03306 pView->setModel(pModel);
03307
03308 KLF_DEBUG_ASSIGN_SAME_REF_INSTANCE(pModel) ;
03309
03310 klfDbg("created model. pModel="<<klfFmtCC("%p", (void*)pModel)<<"; view type="<<pViewType);
03311
03312 #ifdef KLF_DEBUG_USE_MODELTEST
03313 new ModelTest(pModel, this);
03314 #endif
03315
03316 if (pViewType == IconView) {
03317 qobject_cast<KLFLibDefListView*>(pView)->modelInitialized();
03318 } else {
03319 qobject_cast<KLFLibDefTreeView*>(pView)->modelInitialized();
03320 }
03321
03322
03323 QItemSelectionModel *s = pView->selectionModel();
03324 connect(s, SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
03325 this, SLOT(slotViewSelectionChanged(const QItemSelection&, const QItemSelection&)));
03326
03327 connect(pModel, SIGNAL(modelReset()), this, SLOT(slotResourceModelReset()));
03328 connect(pModel, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
03329 this, SLOT(slotResourceDataChanged(const QModelIndex&, const QModelIndex&)));
03330
03331
03332 connect(pModel, SIGNAL(operationStartReportingProgress(KLFProgressReporter *, const QString&)),
03333 this, SIGNAL(operationStartReportingProgress(KLFProgressReporter *, const QString&)));
03334
03335
03336
03337 pDelegate->setSelectionModel(s);
03338
03339 QKeySequence selectAllKey = QKeySequence::SelectAll;
03340 QKeySequence refreshKey = QKeySequence::Refresh;
03341 QAction *selectAllAction = new QAction(tr("Select All", "[[menu action]]"), pView);
03342 selectAllAction->setShortcut(selectAllKey);
03343 connect(selectAllAction, SIGNAL(triggered()), this, SLOT(slotSelectAll()));
03344 QAction *refreshAction = new QAction(tr("Refresh", "[[menu action]]"), pView);
03345 refreshAction->setShortcut(refreshKey);
03346 connect(refreshAction, SIGNAL(triggered()), this, SLOT(slotRefresh()));
03347
03348 QActionGroup * ag = new QActionGroup(pView);
03349 ag->setExclusive(true);
03350 QAction *aPreviewSizeLarge = new QAction(tr("Large", "[[icon preview size menu item]]"), ag);
03351 aPreviewSizeLarge->setCheckable(true);
03352 aPreviewSizeLarge->setData(100);
03353 connect(aPreviewSizeLarge, SIGNAL(triggered()), this, SLOT(slotPreviewSizeFromActionSender()));
03354 QAction *aPreviewSizeMedium = new QAction(tr("Medium", "[[icon preview size menu item]]"), ag);
03355 aPreviewSizeMedium->setCheckable(true);
03356 aPreviewSizeMedium->setData(75);
03357 connect(aPreviewSizeMedium, SIGNAL(triggered()), this, SLOT(slotPreviewSizeFromActionSender()));
03358 QAction *aPreviewSizeSmall = new QAction(tr("Small", "[[icon preview size menu item]]"), ag);
03359 aPreviewSizeSmall->setCheckable(true);
03360 aPreviewSizeSmall->setData(50);
03361 connect(aPreviewSizeSmall, SIGNAL(triggered()), this, SLOT(slotPreviewSizeFromActionSender()));
03362
03363 pPreviewSizeMenu = new QMenu(this);
03364 pPreviewSizeMenu->addAction(aPreviewSizeLarge);
03365 pPreviewSizeMenu->addAction(aPreviewSizeMedium);
03366 pPreviewSizeMenu->addAction(aPreviewSizeSmall);
03367
03368 QAction *aPreviewSize = new QAction(tr("Icon Size", "[[icon preview size option menu]]"), pView);
03369 aPreviewSize->setMenu(pPreviewSizeMenu);
03370
03371 slotPreviewSizeActionsRefreshChecked();
03372
03373 pCommonActions = QList<QAction*>() << selectAllAction << refreshAction << aPreviewSize;
03374 pViewActionsWithShortcut << selectAllAction << refreshAction;
03375
03376 if (pViewType == IconView) {
03377 klfDbg( "About to prepare iconview." ) ;
03378 QAction * iconViewRelayoutAction = new QAction(tr("Relayout All Icons", "[[menu action]]"), this);
03379 connect(iconViewRelayoutAction, SIGNAL(triggered()), this, SLOT(slotRelayoutIcons()));
03380 pIconViewActions = QList<QAction*>() << iconViewRelayoutAction ;
03381 }
03382 if (pViewType == CategoryTreeView || pViewType == ListTreeView) {
03383 QTreeView *treeView = qobject_cast<QTreeView*>(pView);
03384
03385 treeView->setColumnHidden(pModel->columnForEntryPropertyId(KLFLibEntry::Preview), false);
03386 treeView->setColumnHidden(pModel->columnForEntryPropertyId(KLFLibEntry::Latex), true);
03387 treeView->setColumnHidden(pModel->columnForEntryPropertyId(KLFLibEntry::Tags), false);
03388 treeView->setColumnHidden(pModel->columnForEntryPropertyId(KLFLibEntry::Category), true);
03389 treeView->setColumnHidden(pModel->columnForEntryPropertyId(KLFLibEntry::DateTime), true);
03390
03391 for (k = 0; k < pModel->columnCount(); ++k)
03392 treeView->resizeColumnToContents(k);
03393 treeView->setColumnWidth(0, 35+treeView->columnWidth(0));
03394
03395 int col;
03396 QMenu *colMenu = new QMenu(this);
03397 for (col = 0; col < pModel->columnCount(); ++col) {
03398 QString title = pModel->headerData(col, Qt::Horizontal, Qt::DisplayRole).toString();
03399 QAction *a;
03400 a = new QAction(title, this);
03401 a->setProperty("klfModelColumn", col);
03402 a->setCheckable(true);
03403 a->setChecked(!treeView->isColumnHidden(col));
03404 connect(a, SIGNAL(toggled(bool)), this, SLOT(slotShowColumnSenderAction(bool)));
03405 colMenu->addAction(a);
03406 }
03407 QAction *menuAction = new QAction(tr("Show/Hide Columns", "[[menu with sub-menu]]"), this);
03408 menuAction->setMenu(colMenu);
03409 pShowColumnActions = QList<QAction*>() << menuAction;
03410
03411 expandRootNice();
03412 }
03413
03414 updateResourceProp(-1);
03415 updateResourceOwnData(QList<KLFLib::entryId>());
03416
03417 wantMoreCategorySuggestions();
03418 }
03419
03420 void KLFLibDefaultView::expandRootNice()
03421 {
03422 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
03423
03424 if (pViewType == CategoryTreeView) {
03425 klfDbg("is category view.") ;
03426 QTreeView *treeView = qobject_cast<QTreeView*>(pView);
03427
03428
03429 int numRootItems = pModel->rowCount(QModelIndex());
03430 int k;
03431 for (k = 0; k < pModel->rowCount(QModelIndex()); ++k) {
03432 QModelIndex i = pModel->index(k, 0, QModelIndex());
03433 klfDbg("i="<<i<<"; i/rowCount="<<pModel->rowCount(i)<<"; numRootItems="<<numRootItems) ;
03434 if (pModel->rowCount(i) < 6 || numRootItems < 6) {
03435 klfDbg("expanding item i="<<i) ;
03436
03437
03438 treeView->expand(i);
03439 }
03440 }
03441 }
03442 }
03443
03444 void KLFLibDefaultView::updateResourceData(const QString& subRes, int modifyType,
03445 const QList<KLFLib::entryId>& entryIdList)
03446 {
03447 KLF_ASSERT_NOT_NULL( pModel , "Model is NULL!" , return )
03448 ;
03449 klfDbg("The resource modified its data [type="<<modifyType<<"] in subres="<<subRes<<". Our subres="<<resourceEngine()->defaultSubResource()<<"; matches?="<<resourceEngine()->compareDefaultSubResourceEquals(subRes));
03450 if (!resourceEngine()->compareDefaultSubResourceEquals(subRes))
03451 return;
03452 pModel->updateData(entryIdList, modifyType);
03453
03454 updateResourceOwnData(entryIdList);
03455 }
03456 void KLFLibDefaultView::updateResourceOwnData(const QList<KLFLib::entryId>& )
03457 {
03459 klfDbg( KLF_FUNC_NAME ) ;
03460 if (pViewType == IconView) {
03461
03462 }
03463 }
03464 void KLFLibDefaultView::updateResourceProp(int propId)
03465 {
03466 klfDbg( "propId="<<propId ) ;
03467
03468 KLF_ASSERT_NOT_NULL( resourceEngine() , "Resource Engine is NULL, skipping !" , return ) ;
03469
03470
03471 }
03472
03473 void KLFLibDefaultView::showEvent(QShowEvent *event)
03474 {
03475 if (pModel)
03476 pModel->setFetchBatchCount(80);
03477 KLFAbstractLibView::showEvent(event);
03478 }
03479
03480
03481 QListView::Flow KLFLibDefaultView::iconViewFlow() const
03482 {
03483 if (pViewType == IconView) {
03484 KLFLibDefListView *lv = qobject_cast<KLFLibDefListView*>(pView);
03485 KLF_ASSERT_NOT_NULL( lv, "KLFLibDefListView List View is NULL in view type "<<pViewType<<" !!",
03486 return QListView::TopToBottom)
03487 ;
03488 return lv->flow();
03489 }
03490 qWarning()<<KLF_FUNC_NAME<<": requesting icon view flow in the wrong mode `"<<pViewType
03491 <<"'. Should only be called for icon view modes.";
03492 return QListView::TopToBottom;
03493 }
03494
03495
03496 QStringList KLFLibDefaultView::getCategorySuggestions()
03497 {
03498 return pModel->categoryList();
03499 }
03500
03501
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513
03514
03515
03516
03517
03518
03519
03520
03521
03522
03523
03524
03525 bool KLFLibDefaultView::selectEntries(const QList<KLFLib::entryId>& idList)
03526 {
03527 klfDbg("selecting entries: "<<idList) ;
03528
03529 QModelIndexList mil = pModel->findEntryIdList(idList);
03530 QItemSelection sel;
03531 int k;
03532 for (k = 0; k < mil.size(); ++k)
03533 sel << QItemSelectionRange(mil[k]);
03534
03535 pView->selectionModel()->select(sel, QItemSelectionModel::ClearAndSelect);
03536
03537 if (pViewType == CategoryTreeView && pView->inherits("KLFLibDefTreeView")) {
03538 KLFLibDefTreeView *v = qobject_cast<KLFLibDefTreeView*>(pView);
03539 v->ensureExpandedTo(mil);
03540 }
03541 return true;
03542 }
03543
03544
03545
03546 void KLFLibDefaultView::restore(uint restoreflags)
03547 {
03548 QModelIndexList sel = selectedEntryIndexes();
03549 if (sel.size() != 1) {
03550 qWarning("KLFLibDefaultView::restoreWithStyle(): Cannot restore: %d items selected.", sel.size());
03551 return;
03552 }
03553
03554 KLFLibEntry e = sel[0].data(KLFLibModel::FullEntryItemRole).value<KLFLibEntry>();
03555
03556 emit requestRestore(e, restoreflags);
03557 }
03558
03559 void KLFLibDefaultView::showColumns(int propIdColumn, bool show)
03560 {
03561 if ( ! pView->inherits("QTreeView") ) {
03562 qWarning("KLFLibDefaultView::showColumns(%d,%s): Resource view for %s: view does not inherit QTreeView!",
03563 propIdColumn, show?"[show]":"[hide]", qPrintable(resourceEngine()->url().toString()));
03564 return;
03565 }
03566 int colNo = pModel->columnForEntryPropertyId(propIdColumn);
03567 qobject_cast<QTreeView*>(pView)->setColumnHidden(colNo, show);
03568 }
03569
03570 void KLFLibDefaultView::sortBy(int propIdColumn, Qt::SortOrder sortorder)
03571 {
03572 if ( ! pView->inherits("QTreeView") ) {
03573 qWarning("KLFLibDefaultView::showBy(%d,%s): Resource view for %s: view does not inherit QTreeView!",
03574 propIdColumn, (sortorder == Qt::AscendingOrder)?"[Ascending]":"[Descending]" ,
03575 qPrintable(resourceEngine()->url().toString()));
03576 return;
03577 }
03578 QTreeView * tree = qobject_cast<QTreeView*>(pView);
03579 int colNo = pModel->columnForEntryPropertyId(propIdColumn);
03580 if (colNo < 0 || colNo >= pModel->columnCount()) {
03581 qWarning("KLFLibDefaultView::showBy(%d,%s): column number %d is not valid or hidden!",
03582 propIdColumn, (sortorder == Qt::AscendingOrder)?"[Ascending]":"[Descending]", colNo);
03583 return;
03584 }
03585 tree->sortByColumn(colNo, sortorder);
03586 }
03587
03588
03589 void KLFLibDefaultView::slotSelectAll(bool expandItems)
03590 {
03591 slotSelectAll( QModelIndex(), NoSignals | (expandItems?ExpandItems:0) );
03592 updateDisplay();
03593 }
03594 void KLFLibDefaultView::slotSelectAll(const QModelIndex& parent, uint selectAllFlags)
03595 {
03596 KLFDelayedPleaseWaitPopup pleaseWait(tr("Fetching and selecting all, please wait ..."), this);
03597 pleaseWait.setDisableUi(true);
03598 pleaseWait.setDelay(500);
03599
03600 if (selectAllFlags & NoSignals)
03601 pView->selectionModel()->blockSignals(true);
03602
03603 QTime tm;
03604 tm.start();
03605 func_selectAll(parent, selectAllFlags, &tm, &pleaseWait);
03606
03607 if (selectAllFlags & NoSignals)
03608 pView->selectionModel()->blockSignals(false);
03609
03610 emit entriesSelected(selectedEntries());
03611 updateDisplay();
03612 }
03613
03614
03615 bool KLFLibDefaultView::func_selectAll(const QModelIndex& parent, uint selectAllFlags, QTime *tm,
03616 KLFDelayedPleaseWaitPopup *pleaseWait)
03617 {
03618 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
03619
03620
03621 while (pModel->canFetchMore(parent)) {
03622 pModel->fetchMore(parent);
03623 pleaseWait->process();
03624 if (pleaseWait->wasUserDiscarded())
03625 return false;
03626 if (tm->elapsed() > 300) {
03627
03628 qApp->processEvents();
03629 tm->restart();
03630 }
03631 }
03632
03633 int k;
03634 QModelIndex topLeft = pModel->index(0, 0, parent);
03635 QModelIndex bottomRight = pModel->index(pModel->rowCount(parent)-1,
03636 pModel->columnCount(parent)-1, parent);
03637 pView->selectionModel()->select(QItemSelection(topLeft, bottomRight), QItemSelectionModel::Select);
03638 if ( ! pModel->hasChildren(parent) )
03639 return true;
03640
03641 if (selectAllFlags & ExpandItems) {
03642 QTreeView *treeView = pView->inherits("QTreeView") ? qobject_cast<QTreeView*>(pView) : NULL;
03643 if (treeView != NULL)
03644 treeView->expand(parent);
03645 }
03646
03647 for (k = 0; k < pModel->rowCount(parent); ++k) {
03648 QModelIndex child = pModel->index(k, 0, parent);
03649 if ( ! func_selectAll(child, selectAllFlags, tm, pleaseWait) )
03650 return false;
03651 if (tm->elapsed() > 300) {
03652 qApp->processEvents();
03653 pleaseWait->process();
03654 if (pleaseWait->wasUserDiscarded())
03655 return false;
03656 tm->restart();
03657 }
03658 }
03659
03660 return true;
03661 }
03662
03663 void KLFLibDefaultView::slotRefresh()
03664 {
03665 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
03666 pModel->completeRefresh();
03667 }
03668
03669 void KLFLibDefaultView::slotPreviewSizeFromActionSender()
03670 {
03671 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
03672 QAction *a = qobject_cast<QAction*>(sender());
03673 KLF_ASSERT_NOT_NULL(a, "action sender is NULL!", return ; ) ;
03674
03675 pDelegate->setPreviewSize(klfconfig.UI.labelOutputFixedSize * a->data().toInt() / 100.0);
03676 pView->reset();
03677
03678 slotPreviewSizeActionsRefreshChecked();
03679 }
03680
03681 void KLFLibDefaultView::slotPreviewSizeActionsRefreshChecked()
03682 {
03683 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
03684
03685 KLF_ASSERT_NOT_NULL(pPreviewSizeMenu, "pPreviewSizeMenu is NULL!", return ) ;
03686
03687 int curPreviewSizePercent
03688 = pDelegate->previewSize().width() * 100 / klfconfig.UI.labelOutputFixedSize.width();
03689
03690 curPreviewSizePercent = (int)(curPreviewSizePercent/5 +0.5)*5;
03691
03692 QList<QAction*> alist = pPreviewSizeMenu->actions();
03693 klfDbg("There are "<<alist.size()<<" actions...") ;
03694 for (QList<QAction*>::iterator it = alist.begin(); it != alist.end(); ++it) {
03695 QAction *a = (*it);
03696 int a_sz = (int)(a->data().toInt()/5 +0.5)*5;
03697 klfDbg("Processing action "<< a->text() << " (data="<<a->data().toInt()<<" ~= "<<a_sz
03698 <<") curPreviewSizePercent="<<curPreviewSizePercent) ;
03699
03700 if ( a_sz == curPreviewSizePercent )
03701 a->setChecked(true);
03702 else
03703 a->setChecked(false);
03704 }
03705 }
03706
03707
03708 void KLFLibDefaultView::slotRelayoutIcons()
03709 {
03710 if (pViewType != IconView || !pView->inherits("KLFLibDefListView")) {
03711 return;
03712 }
03713 KLFLibDefListView *lv = qobject_cast<KLFLibDefListView*>(pView);
03714
03715 lv->forceRelayout();
03716 }
03717
03718 void KLFLibDefaultView::setIconViewFlow(QListView::Flow flow)
03719 {
03720 if (pViewType == IconView) {
03721 KLFLibDefListView *lv = qobject_cast<KLFLibDefListView*>(pView);
03722 KLF_ASSERT_NOT_NULL( lv, "KLFLibDefListView List View is NULL in view type "<<pViewType<<" !!",
03723 return )
03724 ;
03725
03726 lv->setFlow(flow);
03727 }
03728 }
03729
03730 void KLFLibDefaultView::updateDisplay()
03731 {
03732 KLF_ASSERT_NOT_NULL(pView, "view is NULL!", return ) ;
03733 pView->viewport()->update();
03734 }
03735
03736 bool KLFLibDefaultView::searchFind(const QString& queryString, bool forward)
03737 {
03738 QModelIndex fromIndex = currentVisibleIndex();
03739
03740 fromIndex = pModel->walkPrevIndex(fromIndex);
03741 QModelIndex i = pModel->searchFind(queryString, fromIndex, forward);
03742 pDelegate->setSearchString(queryString);
03743
03744
03745 searchFound(i);
03746 return i.isValid();
03747 }
03748
03749 bool KLFLibDefaultView::searchFindNext(bool forward)
03750 {
03751 QModelIndex i = pModel->searchFindNext(forward);
03752 searchFound(i);
03753 return i.isValid();
03754 }
03755
03756 void KLFLibDefaultView::searchAbort()
03757 {
03758 pModel->searchAbort();
03759 pDelegate->setSearchString(QString());
03760 pDelegate->setSearchIndex(QModelIndex());
03761 updateDisplay();
03762
03763
03764
03765 }
03766
03767
03768 void KLFLibDefaultView::searchFound(const QModelIndex& i)
03769 {
03770 pDelegate->setSearchIndex(i);
03771 if ( ! i.isValid() ) {
03772 pView->scrollToTop();
03773
03774 pView->selectionModel()->setCurrentIndex(QModelIndex(), QItemSelectionModel::Clear);
03775 return;
03776 } else {
03777 pView->scrollTo(i, QAbstractItemView::EnsureVisible);
03778 }
03779 if (pViewType == CategoryTreeView) {
03780
03781 qobject_cast<QTreeView*>(pView)->expand(i);
03782 }
03783
03784 pView->selectionModel()->setCurrentIndex(i,
03785 QItemSelectionModel::ClearAndSelect|
03786 QItemSelectionModel::Rows);
03787 updateDisplay();
03788 }
03789
03790
03791 void KLFLibDefaultView::slotViewSelectionChanged(const QItemSelection& ,
03792 const QItemSelection& )
03793 {
03794 #ifndef Q_WS_WIN
03795
03796
03797 updateDisplay();
03798 #endif
03799
03800 emit entriesSelected(selectedEntries());
03801 }
03802
03803 void KLFLibDefaultView::slotResourceModelReset()
03804 {
03805 if (pViewType == CategoryTreeView) {
03806 expandRootNice();
03807 }
03808 }
03809
03810 void KLFLibDefaultView::slotResourceDataChanged(const QModelIndex& topLeft,
03811 const QModelIndex& bottomRight)
03812 {
03813 QItemSelectionRange rng = QItemSelectionRange(topLeft, bottomRight);
03814 QModelIndexList indexes = rng.indexes();
03815 QList<KLFLib::entryId> eids = pModel->entryIdForIndexList(indexes);
03816 emit resourceDataChanged(eids);
03817 }
03818
03819
03820
03821
03822
03823
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857
03858
03859
03860
03861
03862
03863
03864
03865
03866
03867
03868 void KLFLibDefaultView::slotViewItemClicked(const QModelIndex& index)
03869 {
03870 KLF_DEBUG_TIME_BLOCK(KLF_FUNC_NAME) ;
03871
03872 if (index.column() != 0)
03873 return;
03874
03875 slotSelectAll(index, ExpandItems);
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885 }
03886 void KLFLibDefaultView::slotEntryDoubleClicked(const QModelIndex& index)
03887 {
03888 if (index.data(KLFLibModel::ItemKindItemRole).toInt() != KLFLibModel::EntryKind)
03889 return;
03890 emit requestRestore(index.data(KLFLibModel::FullEntryItemRole).value<KLFLibEntry>(),
03891 KLFLib::RestoreLatex|KLFLib::RestoreStyle);
03892 }
03893
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903 void KLFLibDefaultView::slotShowColumnSenderAction(bool showCol)
03904 {
03905 QObject *a = sender();
03906 if (a == NULL)
03907 return;
03908
03909 if ( ! pView->inherits("QTreeView") )
03910 return;
03911 int colNo = a->property("klfModelColumn").toInt();
03912 qobject_cast<QTreeView*>(pView)->setColumnHidden(colNo, !showCol);
03913 }
03914
03915
03916
03917
03918 QModelIndexList KLFLibDefaultView::selectedEntryIndexes() const
03919 {
03922 QModelIndexList selection = pView->selectionModel()->selectedIndexes();
03923 QModelIndexList entryindexes;
03924 int k;
03925 QList<KLFLib::entryId> doneEntryIds;
03926
03927 for (k = 0; k < selection.size(); ++k) {
03928 KLFLib::entryId eid = selection[k].data(KLFLibModel::EntryIdItemRole).toInt();
03929 int iPos = qLowerBound(doneEntryIds.begin(), doneEntryIds.end(), eid) - doneEntryIds.begin();
03930 if ( iPos < doneEntryIds.size() && doneEntryIds[iPos] == eid )
03931 continue;
03932 doneEntryIds.insert(iPos, eid);
03933 entryindexes << selection[k];
03934 }
03935 return entryindexes;
03936 }
03937
03938
03939
03940
03941
03942 static QStringList defaultViewTypeIds = QStringList()<<"default"<<"default+list"<<"default+icons";
03943
03944
03945 KLFLibDefaultViewFactory::KLFLibDefaultViewFactory(QObject *parent)
03946 : KLFLibViewFactory(defaultViewTypeIds, parent)
03947 {
03948 }
03949
03950
03951 QString KLFLibDefaultViewFactory::viewTypeTitle(const QString& viewTypeIdent) const
03952 {
03953 if (viewTypeIdent == "default")
03954 return tr("Category Tree View");
03955 if (viewTypeIdent == "default+list")
03956 return tr("List View");
03957 if (viewTypeIdent == "default+icons")
03958 return tr("Icon View");
03959
03960 return QString();
03961 }
03962
03963
03964 KLFAbstractLibView * KLFLibDefaultViewFactory::createLibView(const QString& viewTypeIdent,
03965 QWidget *parent,
03966 KLFLibResourceEngine *resourceEngine)
03967 {
03968 KLFLibDefaultView::ViewType v = KLFLibDefaultView::CategoryTreeView;
03969 if (viewTypeIdent == "default")
03970 v = KLFLibDefaultView::CategoryTreeView;
03971 else if (viewTypeIdent == "default+list")
03972 v = KLFLibDefaultView::ListTreeView;
03973 else if (viewTypeIdent == "default+icons")
03974 v = KLFLibDefaultView::IconView;
03975
03976 KLFLibDefaultView *view = new KLFLibDefaultView(parent, v);
03977 view->setResourceEngine(resourceEngine);
03978 return view;
03979 }
03980
03981
03982
03983
03984
03985
03986 KLFLibOpenResourceDlg::KLFLibOpenResourceDlg(const QUrl& defaultlocation, QWidget *parent)
03987 : QDialog(parent)
03988 {
03989 pUi = new Ui::KLFLibOpenResourceDlg;
03990 pUi->setupUi(this);
03991 setWindowIcon(QPixmap(":/pics/klatexformula-64.png"));
03992
03993
03994 KLFLibEngineFactory *efactory = NULL;
03995 if (!defaultlocation.isEmpty())
03996 KLFLibEngineFactory::findFactoryFor(defaultlocation.scheme());
03997 QString defaultwtype;
03998 if (efactory == NULL) {
03999 if (!defaultlocation.isEmpty())
04000 qWarning()<<"No Factory for URL "<<defaultlocation<<"'s scheme!";
04001 } else {
04002 defaultwtype = efactory->correspondingWidgetType(defaultlocation.scheme());
04003 }
04004
04005
04006 QStringList wtypeList = KLFLibWidgetFactory::allSupportedWTypes();
04007 int k;
04008 for (k = 0; k < wtypeList.size(); ++k) {
04009 qDebug("KLFLibOpenRes.Dlg::[constr.]() Adding widget for wtype %s", qPrintable(wtypeList[k]));
04010 KLFLibWidgetFactory *factory = KLFLibWidgetFactory::findFactoryFor(wtypeList[k]);
04011 QUrl thisdefaultlocation;
04012 if (wtypeList[k] == defaultwtype)
04013 thisdefaultlocation = defaultlocation;
04014 QWidget *openWidget = factory->createPromptUrlWidget(pUi->stkOpenWidgets, wtypeList[k],
04015 thisdefaultlocation);
04016 pUi->stkOpenWidgets->insertWidget(k, openWidget);
04017 pUi->cbxType->insertItem(k, factory->widgetTypeTitle(wtypeList[k]),
04018 QVariant::fromValue(wtypeList[k]));
04019
04020 connect(openWidget, SIGNAL(readyToOpen(bool)), this, SLOT(updateReadyToOpenFromSender(bool)));
04021 }
04022
04023 if (defaultwtype.isEmpty()) {
04024 pUi->cbxType->setCurrentIndex(0);
04025 pUi->stkOpenWidgets->setCurrentIndex(0);
04026 } else {
04027 pUi->cbxType->setCurrentIndex(k = wtypeList.indexOf(defaultwtype));
04028 pUi->stkOpenWidgets->setCurrentIndex(k);
04029 }
04030
04031 btnGo = pUi->btnBar->button(QDialogButtonBox::Open);
04032
04033 connect(pUi->cbxType, SIGNAL(activated(int)), this, SLOT(updateReadyToOpen()));
04034 updateReadyToOpen();
04035 }
04036
04037 KLFLibOpenResourceDlg::~KLFLibOpenResourceDlg()
04038 {
04039 delete pUi;
04040 }
04041
04042 QUrl KLFLibOpenResourceDlg::retrieveRawUrl() const
04043 {
04044 int k = pUi->cbxType->currentIndex();
04045 QString wtype = pUi->cbxType->itemData(k).toString();
04046 KLFLibWidgetFactory *factory
04047 = KLFLibWidgetFactory::findFactoryFor(wtype);
04048 return factory->retrieveUrlFromWidget(wtype, pUi->stkOpenWidgets->widget(k));
04049 }
04050
04051 QUrl KLFLibOpenResourceDlg::url() const
04052 {
04053 QUrl url = retrieveRawUrl();
04054 if (url.isEmpty()) {
04055
04056 return QUrl();
04057 }
04058 if (pUi->chkReadOnly->isChecked())
04059 url.addQueryItem("klfReadOnly", "true");
04060 if (pUi->cbxSubResource->count())
04061 url.addQueryItem("klfDefaultSubResource",
04062 pUi->cbxSubResource->itemData(pUi->cbxSubResource->currentIndex()).toString());
04063 klfDbg( "Got URL: "<<url ) ;
04064 return url;
04065 }
04066
04067 void KLFLibOpenResourceDlg::updateReadyToOpenFromSender(bool isready)
04068 {
04069 QObject *w = sender();
04070
04071 w->setProperty("__klflibopenresourcedlg_readyToOpen", isready);
04072 updateReadyToOpen();
04073 }
04074 void KLFLibOpenResourceDlg::updateReadyToOpen()
04075 {
04076 QWidget *w = pUi->stkOpenWidgets->currentWidget();
04077 KLF_ASSERT_NOT_NULL( w, "widget is NULL!", return ) ;
04078
04079 bool w_is_ready = w->property("readyToOpen").toBool();
04080 if (!w_is_ready) {
04081
04082
04083 QVariant v = w->property("__klflibopenresourcedlg_readyToOpen");
04084 if (v.isValid())
04085 w_is_ready = v.toBool();
04086 }
04087 btnGo->setEnabled(w_is_ready);
04088
04089 pUi->frmSubResource->show();
04090 pUi->cbxSubResource->clear();
04091 if (!w_is_ready) {
04092 pUi->frmSubResource->hide();
04093 } else {
04094
04095 QMap<QString,QString> subResMap = KLFLibEngineFactory::listSubResourcesWithTitles(retrieveRawUrl());
04096 if (subResMap.isEmpty()) {
04097 pUi->frmSubResource->hide();
04098 } else {
04099 for (QMap<QString,QString>::const_iterator it = subResMap.begin(); it != subResMap.end(); ++it) {
04100 QString subres = it.key();
04101 QString subrestitle = it.value();
04102 if (subrestitle.isEmpty())
04103 subrestitle = subres;
04104 pUi->cbxSubResource->addItem(subrestitle, QVariant(subres));
04105 }
04106 }
04107 }
04108 }
04109
04110
04111 QUrl KLFLibOpenResourceDlg::queryOpenResource(const QUrl& defaultlocation, QWidget *parent)
04112 {
04113 KLFLibOpenResourceDlg dlg(defaultlocation, parent);
04114 int result = dlg.exec();
04115 if (result != QDialog::Accepted)
04116 return QUrl();
04117 QUrl url = dlg.url();
04118 return url;
04119 }
04120
04121
04122
04123
04124
04125
04126 KLFLibCreateResourceDlg::KLFLibCreateResourceDlg(const QString& defaultWtype, QWidget *parent)
04127 : QDialog(parent)
04128 {
04129 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
04130
04131 pUi = new Ui::KLFLibOpenResourceDlg;
04132 pUi->setupUi(this);
04133 setWindowIcon(QPixmap(":/pics/klatexformula-64.png"));
04134
04135 pUi->lblMain->setText(tr("Create New Library Resource", "[[dialog label title]]"));
04136 setWindowTitle(tr("Create New Library Resource", "[[dialog window title]]"));
04137 pUi->chkReadOnly->hide();
04138
04139 pUi->cbxSubResource->setEnabled(true);
04140 pUi->cbxSubResource->setEditable(true);
04141 pUi->cbxSubResource->setEditText(tr("SubResource1"));
04142
04143 pUi->btnBar->setStandardButtons(QDialogButtonBox::Save|QDialogButtonBox::Cancel);
04144 btnGo = pUi->btnBar->button(QDialogButtonBox::Save);
04145
04146 int defaultIndex = 0;
04147
04148 QStringList wtypeList = KLFLibWidgetFactory::allSupportedWTypes();
04149 int k;
04150 for (k = 0; k < wtypeList.size(); ++k) {
04151 KLFLibWidgetFactory *factory
04152 = KLFLibWidgetFactory::findFactoryFor(wtypeList[k]);
04153 QWidget *createResWidget =
04154 factory->createPromptCreateParametersWidget(pUi->stkOpenWidgets, wtypeList[k],
04155 Parameters());
04156 pUi->stkOpenWidgets->insertWidget(k, createResWidget);
04157 pUi->cbxType->insertItem(k, factory->widgetTypeTitle(wtypeList[k]),
04158 QVariant::fromValue(wtypeList[k]));
04159
04160 if (wtypeList[k] == defaultWtype)
04161 defaultIndex = k;
04162
04163 connect(createResWidget, SIGNAL(readyToCreate(bool)),
04164 this, SLOT(updateReadyToCreateFromSender(bool)));
04165 klfDbg("Added create-res-widget of type "<<wtypeList[k]) ;
04166 }
04167
04168 pUi->cbxType->setCurrentIndex(defaultIndex);
04169 pUi->stkOpenWidgets->setCurrentIndex(defaultIndex);
04170
04171 connect(pUi->cbxType, SIGNAL(activated(int)), this, SLOT(updateReadyToCreate()));
04172 updateReadyToCreate();
04173 }
04174 KLFLibCreateResourceDlg::~KLFLibCreateResourceDlg()
04175 {
04176 delete pUi;
04177 }
04178
04179 KLFLibEngineFactory::Parameters KLFLibCreateResourceDlg::getCreateParameters() const
04180 {
04181 KLF_DEBUG_BLOCK(KLF_FUNC_NAME) ;
04182
04183 int k = pUi->cbxType->currentIndex();
04184 QString wtype = pUi->cbxType->itemData(k).toString();
04185 KLFLibWidgetFactory *factory
04186 = KLFLibWidgetFactory::findFactoryFor(wtype);
04187 Parameters p = factory->retrieveCreateParametersFromWidget(wtype, pUi->stkOpenWidgets->widget(k));
04188 p["klfWidgetType"] = wtype;
04189 p["klfDefaultSubResource"] = pUi->cbxSubResource->currentText();
04190 p["klfDefaultSubResourceTitle"] = pUi->cbxSubResource->currentText();
04191
04192 klfDbg("Create parameters are: "<<p) ;
04193
04194 return p;
04195 }
04196
04197
04198 void KLFLibCreateResourceDlg::accept()
04199 {
04200 const Parameters p = getCreateParameters();
04201 if (p == Parameters() || p["klfCancel"].toBool() == true) {
04202 QDialog::reject();
04203 return;
04204 }
04205 if (p["klfRetry"].toBool() == true)
04206 return;
04207
04208
04209
04210
04211 pParam = p;
04212 QDialog::accept();
04213 }
04214 void KLFLibCreateResourceDlg::reject()
04215 {
04216 QDialog::reject();
04217 }
04218
04219 void KLFLibCreateResourceDlg::updateReadyToCreateFromSender(bool isready)
04220 {
04221 QObject *w = sender();
04222 w->setProperty("__klflibcreateresourcedlg_readyToCreate", isready);
04223 updateReadyToCreate();
04224 }
04225 void KLFLibCreateResourceDlg::updateReadyToCreate()
04226 {
04227 QWidget *w = pUi->stkOpenWidgets->currentWidget();
04228 if (w == NULL) return;
04229 QVariant v = w->property("__klflibcreateresourcedlg_readyToCreate");
04230
04231
04232 btnGo->setEnabled(!v.isValid() || v.toBool());
04233 }
04234
04235
04236 KLFLibResourceEngine *KLFLibCreateResourceDlg::createResource(const QString& defaultWtype,
04237 QObject *resourceParent, QWidget *parent)
04238 {
04239 KLFLibCreateResourceDlg dlg(defaultWtype, parent);
04240 int result = dlg.exec();
04241 if (result != QDialog::Accepted)
04242 return NULL;
04243
04244 Parameters p = dlg.pParam;
04245 QString scheme = p["klfScheme"].toString();
04246
04247 if (scheme.isEmpty()) {
04248 qWarning()<<"KLFLibCr.Res.Dlg::createRes.(): Widget Type "<<p["klfWidgetType"]
04249 <<" failed to announce what scheme it wanted in p[\"klfScheme\"]!";
04250 return NULL;
04251 }
04252
04253 KLFLibEngineFactory * factory = KLFLibEngineFactory::findFactoryFor(scheme);
04254 KLF_ASSERT_NOT_NULL( factory ,
04255 qPrintable(QString("Couldn't find factory for scheme %1 ?!?").arg(scheme)),
04256 return NULL )
04257 ;
04258
04259 KLFLibResourceEngine *resource = factory->createResource(scheme, p, resourceParent);
04260 return resource;
04261 }
04262
04263
04264
04265
04266
04267 KLFLibResPropEditor::KLFLibResPropEditor(KLFLibResourceEngine *res, QWidget *parent)
04268 : QWidget(parent)
04269 {
04270 U = new Ui::KLFLibResPropEditor;
04271 U->setupUi(this);
04272 setWindowIcon(QPixmap(":/pics/klatexformula-64.png"));
04273
04274 QPalette pal = U->txtUrl->palette();
04275 pal.setColor(QPalette::Base, pal.color(QPalette::Window));
04276 pal.setColor(QPalette::Background, pal.color(QPalette::Window));
04277 U->txtUrl->setPalette(pal);
04278
04279 if (res == NULL)
04280 qWarning("KLFLibResPropEditor: NULL Resource! Expect CRASH!");
04281
04282 pResource = res;
04283
04284 pSuppSubRes =
04285 (pResource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResources);
04286 pSuppSubResProps =
04287 (pResource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResourceProps) ;
04288
04289 connect(pResource, SIGNAL(resourcePropertyChanged(int)),
04290 this, SLOT(slotResourcePropertyChanged(int)));
04291 connect(pResource, SIGNAL(subResourcePropertyChanged(const QString&, int)),
04292 this, SLOT(slotSubResourcePropertyChanged(const QString&, int)));
04293
04294 pPropModel = new QStandardItemModel(this);
04295 pPropModel->setColumnCount(2);
04296 pPropModel->setHorizontalHeaderLabels(QStringList() << tr("Name") << tr("Value"));
04297 U->tblProperties->setModel(pPropModel);
04298 U->tblProperties->setItemDelegate(new QItemDelegate(this));
04299
04300 connect(pPropModel, SIGNAL(itemChanged(QStandardItem *)),
04301 this, SLOT(advPropEdited(QStandardItem *)));
04302
04303 pSubResPropModel = new QStandardItemModel(this);
04304 pSubResPropModel->setColumnCount(2);
04305 pSubResPropModel->setHorizontalHeaderLabels(QStringList() << tr("Name") << tr("Value"));
04306 U->tblSubResProperties->setModel(pSubResPropModel);
04307 U->tblSubResProperties->setItemDelegate(new QItemDelegate(this));
04308
04309 connect(pSubResPropModel, SIGNAL(itemChanged(QStandardItem *)),
04310 this, SLOT(advSubResPropEdited(QStandardItem *)));
04311
04312 U->frmAdvanced->setShown(U->btnAdvanced->isChecked());
04313
04314
04315 updateResourceProperties();
04316
04317 updateSubResources(pResource->defaultSubResource());
04318
04319 updateSubResourceProperties();
04320
04321 connect(U->btnApply, SIGNAL(clicked()), this, SLOT(apply()));
04322 }
04323
04324 KLFLibResPropEditor::~KLFLibResPropEditor()
04325 {
04326 delete U;
04327 }
04328
04329 bool KLFLibResPropEditor::apply()
04330 {
04331 bool res = true;
04332
04333
04334 if (pResource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResources)
04335 pResource->setDefaultSubResource(curSubResource());
04336
04337 bool srislocked = false;
04338 if (pSuppSubRes && pSuppSubResProps)
04339 srislocked = pResource->subResourceProperty(curSubResource(),
04340 KLFLibResourceEngine::SubResPropLocked).toBool();
04341
04342 bool lockmodified = (pResource->locked() != U->chkLocked->isChecked());
04343 bool srlockmodified = false;
04344 if (pSuppSubRes && pSuppSubResProps && srislocked != U->chkSubResLocked->isChecked()) {
04345 srlockmodified = true;
04346 }
04347 bool wantunlock = lockmodified && !U->chkLocked->isChecked();
04348 bool srwantunlock = srlockmodified && !U->chkSubResLocked->isChecked();
04349 bool wantlock = lockmodified && !wantunlock;
04350 bool srwantlock = srlockmodified && !srwantunlock;
04351 bool titlemodified = (pResource->title() != U->txtTitle->text());
04352 bool subrestitlemodified = false;
04353 if (pSuppSubRes && pSuppSubResProps &&
04354 pResource->subResourceProperty(curSubResource(), KLFLibResourceEngine::SubResPropTitle).toString()
04355 != U->txtSubResTitle->text()) {
04356 subrestitlemodified = true;
04357 }
04358
04359 klfDbg( ": lockmodif="<<lockmodified<<"; srlockmodified="<<srlockmodified
04360 <<"; wantunlock="<<wantunlock<<"; srwantunlock="<<srwantunlock<<"; wantlock="<<wantlock
04361 <<"; srwantlock="<<srwantlock<<"; titlemodif="<<titlemodified
04362 <<"; srtitlemodif="<<subrestitlemodified ) ;
04363
04364 if ( (pResource->locked() && !lockmodified) ||
04365 (srislocked && !srlockmodified) ) {
04366
04367 if (titlemodified || subrestitlemodified) {
04368 QMessageBox::critical(this, tr("Error"), tr("Can't rename a locked resource!"));
04369 return false;
04370 } else {
04371 return true;
04372 }
04373 }
04374 if (wantunlock) {
04375 if ( ! pResource->setLocked(false) ) {
04376 res = false;
04377 QMessageBox::critical(this, tr("Error"), tr("Failed to unlock resource."));
04378 }
04379 }
04380 if (srwantunlock) {
04381 if ( ! pResource->setSubResourceProperty(curSubResource(), KLFLibResourceEngine::SubResPropLocked,
04382 false) ) {
04383 res = false;
04384 QMessageBox::critical(this, tr("Error"), tr("Failed to unlock sub-resource \"%1\".")
04385 .arg(curSubResource()));
04386 }
04387 }
04388
04389 QString newTitle = U->txtTitle->text();
04390 QString newSubResTitle = U->txtSubResTitle->text();
04391
04392 if ( titlemodified && ! pResource->setTitle(newTitle) ) {
04393 res = false;
04394 QMessageBox::critical(this, tr("Error"), tr("Failed to rename resource."));
04395 }
04396
04397 if ( subrestitlemodified &&
04398 ! pResource->setSubResourceProperty(curSubResource(),
04399 KLFLibResourceEngine::SubResPropTitle,
04400 newSubResTitle) ) {
04401 res = false;
04402 QMessageBox::critical(this, tr("Error"), tr("Failed to rename sub-resource \"%1\".")
04403 .arg(curSubResource()));
04404 }
04405
04406 if (wantlock) {
04407 if ( ! pResource->setLocked(true) ) {
04408 res = false;
04409 QMessageBox::critical(this, tr("Error"), tr("Failed to lock resource."));
04410 }
04411 }
04412 if (srwantlock) {
04413 if ( ! pResource->setSubResourceProperty(curSubResource(), KLFLibResourceEngine::SubResPropLocked,
04414 true) ) {
04415 res = false;
04416 QMessageBox::critical(this, tr("Error"), tr("Failed to lock sub-resource \"%1\".")
04417 .arg(curSubResource()));
04418 }
04419 }
04420
04421 return res;
04422 }
04423
04424 void KLFLibResPropEditor::on_btnAdvanced_toggled(bool on)
04425 {
04426
04427 U->frmAdvanced->setShown(on);
04428 if (U->frmAdvanced->isVisible()) {
04429
04430 int w = width() / 3;
04431 U->tblProperties->setColumnWidth(0, w);
04432 U->tblProperties->setColumnWidth(1, w);
04433 U->tblSubResProperties->setColumnWidth(0, w);
04434 U->tblSubResProperties->setColumnWidth(1, w);
04435 }
04436 update();
04437 adjustSize();
04438 if (parentWidget()) {
04439 klfDbg( "Parent widget is "<<parentWidget() ) ;
04440 parentWidget()->update();
04441 parentWidget()->adjustSize();
04442 }
04443 }
04444
04445 void KLFLibResPropEditor::updateSubResources(const QString& curSubRes)
04446 {
04447 klfDbg( "KLFLibResPropEditor::updateSubResources("<<curSubRes<<")" ) ;
04448 if ( pSuppSubRes ) {
04449 U->cbxSubResource->blockSignals(true);
04450 U->cbxSubResource->clear();
04451 QStringList subResList = pResource->subResourceList();
04452 int k;
04453 int curSubResIndex = 0;
04454 for (k = 0; k < subResList.size(); ++k) {
04455 QString title;
04456 QString thissrtitle
04457 = pResource->subResourceProperty(subResList[k], KLFLibResourceEngine::SubResPropTitle).toString();
04458 if (!thissrtitle.isEmpty())
04459 title = QString("%1 (%2)").arg(thissrtitle, subResList[k]);
04460 else
04461 title = subResList[k];
04462 U->cbxSubResource->addItem(title, subResList[k]);
04463 if (subResList[k] == curSubRes)
04464 curSubResIndex = k;
04465 }
04466 klfDbg( "KLFLibResPropEditor::updateSubResources("<<curSubRes<<") : setting cur index="<<curSubResIndex ) ;
04467 U->cbxSubResource->setCurrentIndex(curSubResIndex);
04468 U->cbxSubResource->blockSignals(false);
04469 if ( pSuppSubResProps ) {
04470 U->wSubResProps->show();
04471 U->txtSubResTitle->setEnabled(true);
04472 U->chkSubResLocked->setEnabled(true);
04473 slotSubResourcePropertyChanged(curSubResource(), -2);
04474 U->txtSubResTitle->setEnabled(pResource
04475 ->canModifySubResourceProperty(curSubResource(),
04476 KLFLibResourceEngine::SubResPropTitle));
04477 U->txtSubResTitle->setText(pResource->subResourceProperty(curSubResource(),
04478 KLFLibResourceEngine::SubResPropTitle)
04479 .toString());
04480 U->chkSubResLocked->setEnabled(pResource
04481 ->canModifySubResourceProperty(curSubResource(),
04482 KLFLibResourceEngine::SubResPropLocked));
04483 U->chkSubResLocked->setChecked(pResource->subResourceProperty(curSubResource(),
04484 KLFLibResourceEngine::SubResPropLocked)
04485 .toBool());
04486 } else {
04487 U->wSubResProps->hide();
04488 U->chkSubResLocked->setEnabled(false);
04489 U->txtSubResTitle->setText("");
04490 U->txtSubResTitle->setEnabled(false);
04491 }
04492 } else {
04493 U->cbxSubResource->clear();
04494 U->cbxSubResource->setEnabled(false);
04495 U->wSubResProps->hide();
04496 U->chkSubResLocked->setEnabled(false);
04497 U->txtSubResTitle->setText("");
04498 U->txtSubResTitle->setEnabled(false);
04499 }
04500 }
04501
04502 void KLFLibResPropEditor::advPropEdited(QStandardItem *item)
04503 {
04504 klfDbg( "advPropEdited("<<item<<")" ) ;
04505 QVariant value = item->data(Qt::EditRole);
04506 int propId = item->data(Qt::UserRole).toInt();
04507 bool r = pResource->setResourceProperty(propId, value);
04508 if ( ! r ) {
04509 QMessageBox::critical(this, tr("Error"),
04510 tr("Failed to set resource property \"%1\".")
04511 .arg(pResource->propertyNameForId(propId)));
04512 }
04513
04514 }
04515
04516 void KLFLibResPropEditor::slotResourcePropertyChanged(int )
04517 {
04518
04519 updateResourceProperties();
04520 updateSubResources();
04521 }
04522 void KLFLibResPropEditor::updateResourceProperties()
04523 {
04524 pPropModel->setRowCount(0);
04525 int k;
04526 QStringList props = pResource->registeredPropertyNameList();
04527 QPalette pal = U->tblSubResProperties->palette();
04528 for (k = 0; k < props.size(); ++k) {
04529 QString prop = props[k];
04530 int propId = pResource->propertyIdForName(prop);
04531 QVariant val = pResource->resourceProperty(prop);
04532 QStandardItem *i1 = new QStandardItem(prop);
04533 i1->setEditable(false);
04534 QStandardItem *i2 = new QStandardItem(val.toString());
04535 bool editable = pResource->canModifyProp(propId);
04536 i2->setEditable(editable);
04537 QPalette::ColorGroup cg = editable ? QPalette::Active : QPalette::Disabled;
04538 i2->setForeground(pal.brush(cg, QPalette::Text));
04539 i2->setBackground(pal.brush(cg, QPalette::Base));
04540 i2->setData(val, Qt::EditRole);
04541 i2->setData(propId, Qt::UserRole);
04542 pPropModel->appendRow(QList<QStandardItem*>() << i1 << i2);
04543 }
04544
04545 U->txtTitle->setText(pResource->title());
04546 U->txtTitle->setEnabled(pResource->canModifyProp(KLFLibResourceEngine::PropTitle));
04547 QString surl = pResource->url().toString();
04548 if (surl.endsWith("?"))
04549 surl.chop(1);
04550 U->txtUrl->setText(surl);
04551 U->chkLocked->setChecked(pResource->locked());
04552 U->chkLocked->setEnabled(pResource->canModifyProp(KLFLibResourceEngine::PropLocked));
04553 }
04554
04555 QString KLFLibResPropEditor::curSubResource() const
04556 {
04557 return U->cbxSubResource->itemData(U->cbxSubResource->currentIndex()).toString();
04558 }
04559
04560 void KLFLibResPropEditor::advSubResPropEdited(QStandardItem *item)
04561 {
04562 klfDbg( "item="<<item<<"" ) ;
04563 QVariant value = item->data(Qt::EditRole);
04564 int propId = item->data(Qt::UserRole).toInt();
04565 bool r = pResource->setSubResourceProperty(curSubResource(), propId, value);
04566 if ( ! r ) {
04567 QMessageBox::critical(this, tr("Error"),
04568 tr("Failed to set sub-resource \"%1\"'s property \"%2\".")
04569 .arg(curSubResource(), propId));
04570 }
04571
04572 }
04573 void KLFLibResPropEditor::on_cbxSubResource_currentIndexChanged(int )
04574 {
04575 slotSubResourcePropertyChanged(curSubResource(), -2);
04576 U->txtSubResTitle->setText(pResource->subResourceProperty(curSubResource(),
04577 KLFLibResourceEngine::SubResPropTitle)
04578 .toString());
04579 U->chkSubResLocked->setChecked(pResource->subResourceProperty(curSubResource(),
04580 KLFLibResourceEngine::SubResPropLocked)
04581 .toBool());
04582 }
04583
04584 void KLFLibResPropEditor::slotSubResourcePropertyChanged(const QString& subResource, int subResPropId)
04585 {
04586 if (subResource != curSubResource())
04587 return;
04588
04589 if (subResPropId != -2) {
04590
04591 updateSubResources(curSubResource());
04592
04593
04594 return;
04595 }
04596
04597 if ( ! pSuppSubResProps )
04598 return;
04599
04600
04601 updateSubResourceProperties();
04602 }
04603 void KLFLibResPropEditor::updateSubResourceProperties()
04604 {
04605
04606 pSubResPropModel->setRowCount(0);
04607 QPalette pal = U->tblSubResProperties->palette();
04608 int k;
04609 QList<int> props = pResource->subResourcePropertyIdList();
04610 for (k = 0; k < props.size(); ++k) {
04611 int propId = props[k];
04612 QVariant val = pResource->subResourceProperty(curSubResource(), propId);
04613 QStandardItem *i1 = new QStandardItem(pResource->subResourcePropertyName(propId));
04614 i1->setEditable(false);
04615 QStandardItem *i2 = new QStandardItem(val.toString());
04616 bool editable = pResource->canModifySubResourceProperty(curSubResource(), propId);
04617 i2->setEditable(editable);
04618 QPalette::ColorGroup cg = editable ? QPalette::Active : QPalette::Disabled;
04619 i2->setForeground(pal.brush(cg, QPalette::Text));
04620 i2->setBackground(pal.brush(cg, QPalette::Base));
04621 i2->setData(val, Qt::EditRole);
04622 i2->setData(propId, Qt::UserRole);
04623 pSubResPropModel->appendRow(QList<QStandardItem*>() << i1 << i2);
04624 }
04625 }
04626
04627
04628
04629
04630
04631
04632
04633
04634 KLFLibResPropEditorDlg::KLFLibResPropEditorDlg(KLFLibResourceEngine *resource, QWidget *parent)
04635 : QDialog(parent)
04636 {
04637 QVBoxLayout *lyt = new QVBoxLayout(this);
04638
04639 pEditor = new KLFLibResPropEditor(resource, this);
04640 lyt->addWidget(pEditor);
04641
04642 QDialogButtonBox *btns = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel,
04643 Qt::Horizontal, this);
04644 lyt->addWidget(btns);
04645
04646 connect(btns->button(QDialogButtonBox::Ok), SIGNAL(clicked()),
04647 this, SLOT(applyAndClose()));
04648
04649
04650 connect(btns->button(QDialogButtonBox::Cancel), SIGNAL(clicked()),
04651 this, SLOT(cancelAndClose()));
04652
04653 setModal(false);
04654 setWindowTitle(pEditor->windowTitle());
04655 setAttribute(Qt::WA_DeleteOnClose, true);
04656 }
04657
04658 KLFLibResPropEditorDlg::~KLFLibResPropEditorDlg()
04659 {
04660 }
04661
04662 void KLFLibResPropEditorDlg::applyAndClose()
04663 {
04664 if (pEditor->apply()) {
04665 accept();
04666 }
04667 }
04668
04669 void KLFLibResPropEditorDlg::cancelAndClose()
04670 {
04671 reject();
04672 }
04673
04674
04675
04676
04677 KLFLibNewSubResDlg::KLFLibNewSubResDlg(KLFLibResourceEngine *resource, QWidget *parent)
04678 : QDialog(parent), isAutoName(true)
04679 {
04680 u = new Ui::KLFLibNewSubResDlg;
04681 u->setupUi(this);
04682 setWindowIcon(QPixmap(":/pics/klatexformula-64.png"));
04683
04684 u->lblNoTitle->hide();
04685
04686 uint fl = resource->supportedFeatureFlags();
04687 if ( (fl & KLFLibResourceEngine::FeatureSubResources) == 0 ) {
04688 u->lblName->setEnabled(false);
04689 u->txtName->setEnabled(false);
04690 u->lblTitle->setEnabled(false);
04691 u->txtTitle->setEnabled(false);
04692 u->btns->button(QDialogButtonBox::Ok)->setEnabled(false);
04693 } else if ( (fl & KLFLibResourceEngine::FeatureSubResourceProps) == 0) {
04694 u->lblTitle->setEnabled(false);
04695 u->txtTitle->setEnabled(false);
04696 u->lblNoTitle->show();
04697 }
04698
04699 u->lblResource->setText(resource->title());
04700 }
04701
04702 KLFLibNewSubResDlg::~KLFLibNewSubResDlg()
04703 {
04704 }
04705
04706 QString KLFLibNewSubResDlg::newSubResourceName() const
04707 {
04708 return u->txtName->text();
04709 }
04710
04711 QString KLFLibNewSubResDlg::newSubResourceTitle() const
04712 {
04713 return u->txtTitle->text();
04714 }
04715
04716
04717 QString KLFLibNewSubResDlg::makeSubResInternalName(const QString& title)
04718 {
04719 QString nm = title;
04720
04721 QRegExp rx("(?:\\s|-)([a-z])");
04722 int i = 0;
04723 while ((i = rx.indexIn(nm,i+1)) >= 0) {
04724 QChar c = rx.cap(1).length() ? rx.cap(1)[0] : QChar('_');
04725 nm.replace(i, rx.matchedLength(), c.toUpper());
04726 }
04727 nm.replace(QRegExp("\\s"), "");
04728 nm.replace(QRegExp("[^A-Za-z0-9_]"), "_");
04729 return nm;
04730 }
04731
04732 void KLFLibNewSubResDlg::on_txtTitle_textChanged(const QString& text)
04733 {
04734 if (isAutoName) {
04735 u->txtName->blockSignals(true);
04736 u->txtName->setText(makeSubResInternalName(text));
04737 u->txtName->blockSignals(false);
04738 }
04739 }
04740
04741 void KLFLibNewSubResDlg::on_txtName_textChanged(const QString& text)
04742 {
04743 if (!text.isEmpty())
04744 isAutoName = false;
04745 else
04746 isAutoName = true;
04747 }
04748
04749 QString KLFLibNewSubResDlg::createSubResourceIn(KLFLibResourceEngine *resource, QWidget *parent)
04750 {
04751 if ( (resource->supportedFeatureFlags() & KLFLibResourceEngine::FeatureSubResources) == 0 ) {
04752 qWarning("KLFLibNewSubResDlg::createSubResourceIn: can't create sub-resource in resource not "
04753 "supporting sub-resources (!) : %s", qPrintable(resource->url().toString()));
04754 return QString();
04755 }
04756 KLFLibNewSubResDlg d(resource, parent);
04757 int r = d.exec();
04758 if (r != QDialog::Accepted)
04759 return QString();
04760 QString name = d.newSubResourceName();
04761 QString title = d.newSubResourceTitle();
04762
04763 bool result = resource->createSubResource(name, title);
04764 if (!result)
04765 return QString();
04766
04767 return name;
04768 }
04769
04770
04771
04772 KLFLibLocalFileSchemeGuesser::KLFLibLocalFileSchemeGuesser()
04773 {
04774 KLFLibBasicWidgetFactory::addLocalFileSchemeGuesser(this);
04775 }
04776 KLFLibLocalFileSchemeGuesser::~KLFLibLocalFileSchemeGuesser()
04777 {
04778 KLFLibBasicWidgetFactory::removeLocalFileSchemeGuesser(this);
04779 }
04780
04781
04782
04783 KLFLibBasicWidgetFactory::KLFLibBasicWidgetFactory(QObject *parent)
04784 : KLFLibWidgetFactory(parent)
04785 {
04786 }
04787 KLFLibBasicWidgetFactory::~KLFLibBasicWidgetFactory()
04788 {
04789 }
04790
04791
04792 QStringList KLFLibBasicWidgetFactory::supportedTypes() const
04793 {
04794 return QStringList() << QLatin1String("LocalFile");
04795 }
04796
04797
04798 QString KLFLibBasicWidgetFactory::widgetTypeTitle(const QString& wtype) const
04799 {
04800 if (wtype == QLatin1String("LocalFile"))
04801 return tr("Local File");
04802 return QString();
04803 }
04804
04805
04806
04807 QWidget * KLFLibBasicWidgetFactory::createPromptUrlWidget(QWidget *parent, const QString& wtype,
04808 QUrl defaultlocation)
04809 {
04810 if (wtype == QLatin1String("LocalFile")) {
04811 KLFLibLocalFileOpenWidget *w = new KLFLibLocalFileOpenWidget(parent, pLocalFileTypes);
04812 w->setUrl(defaultlocation);
04813 return w;
04814 }
04815 return NULL;
04816 }
04817
04818 QUrl KLFLibBasicWidgetFactory::retrieveUrlFromWidget(const QString& wtype, QWidget *widget)
04819 {
04820 if (wtype == "LocalFile") {
04821 if (widget == NULL || !widget->inherits("KLFLibLocalFileOpenWidget")) {
04822 qWarning("KLFLibBasicWidgetFactory::retrieveUrlFromWidget(): Bad Widget provided!");
04823 return QUrl();
04824 }
04825 return qobject_cast<KLFLibLocalFileOpenWidget*>(widget)->url();
04826 } else {
04827 qWarning()<<"KLFLibB.W.Factory::retrieveUrlFromWidget(): Bad widget type: "<<wtype;
04828 return QUrl();
04829 }
04830 }
04831
04832
04833 QWidget *KLFLibBasicWidgetFactory::createPromptCreateParametersWidget(QWidget *parent,
04834 const QString& wtype,
04835 const Parameters& defaultparameters)
04836 {
04837 if (wtype == QLatin1String("LocalFile")) {
04838 KLFLibLocalFileCreateWidget *w = new KLFLibLocalFileCreateWidget(parent, pLocalFileTypes);
04839 w->setUrl(defaultparameters["Url"].toUrl());
04840 return w;
04841 }
04842 return NULL;
04843 }
04844
04845 KLFLibWidgetFactory::Parameters
04846 KLFLibBasicWidgetFactory::retrieveCreateParametersFromWidget(const QString& scheme,
04847 QWidget *widget)
04848 {
04849 if (scheme == QLatin1String("LocalFile")) {
04850 if (widget == NULL || !widget->inherits("KLFLibLocalFileCreateWidget")) {
04851 qWarning("KLFLibBasicWidgetFactory::retrieveUrlFromWidget(): Bad Widget provided!");
04852 return Parameters();
04853 }
04854 KLFLibLocalFileCreateWidget *w = qobject_cast<KLFLibLocalFileCreateWidget*>(widget);
04855 Parameters p;
04856 QString filename = w->selectedFName();
04857 if (QFile::exists(filename) && !w->confirmedOverwrite()) {
04858 QMessageBox::StandardButton result =
04859 QMessageBox::warning(widget, tr("Overwrite?"),
04860 tr("The specified file already exists. Overwrite it?"),
04861 QMessageBox::Yes|QMessageBox::No|QMessageBox::Cancel,
04862 QMessageBox::No);
04863 if (result == QMessageBox::No) {
04864 p["klfRetry"] = true;
04865 return p;
04866 } else if (result == QMessageBox::Cancel) {
04867 return Parameters();
04868 }
04869
04870 bool r = QFile::remove(filename);
04871 if ( !r ) {
04872 QMessageBox::critical(widget, tr("Error"), tr("Failed to overwrite the file %1.")
04873 .arg(filename));
04874 return Parameters();
04875 }
04876 }
04877
04878 p["Filename"] = filename;
04879 p["klfScheme"] = w->selectedScheme();
04880 return p;
04881 }
04882
04883 return Parameters();
04884 }
04885
04886
04887 void KLFLibBasicWidgetFactory::addLocalFileType(const LocalFileType& f)
04888 {
04889 pLocalFileTypes << f;
04890 }
04891
04892
04893 QList<KLFLibBasicWidgetFactory::LocalFileType> KLFLibBasicWidgetFactory::localFileTypes()
04894 {
04895 return pLocalFileTypes;
04896 }
04897
04898
04899
04900 QString KLFLibBasicWidgetFactory::guessLocalFileScheme(const QString& fileName)
04901 {
04902 int k;
04903 for (k = 0; k < pSchemeGuessers.size(); ++k) {
04904 QString s = pSchemeGuessers[k]->guessScheme(fileName);
04905 if (!s.isEmpty())
04906 return s;
04907 }
04908 return QString();
04909 }
04910
04911
04912 void KLFLibBasicWidgetFactory::addLocalFileSchemeGuesser(KLFLibLocalFileSchemeGuesser *schemeguesser)
04913 {
04914 pSchemeGuessers << schemeguesser;
04915 }
04916
04917
04918 void KLFLibBasicWidgetFactory::removeLocalFileSchemeGuesser(KLFLibLocalFileSchemeGuesser *schemeguesser)
04919 {
04920 pSchemeGuessers.removeAll(schemeguesser);
04921 }
04922
04923
04924
04925
04926 QList<KLFLibBasicWidgetFactory::LocalFileType> KLFLibBasicWidgetFactory::pLocalFileTypes ;
04927
04928 QList<KLFLibLocalFileSchemeGuesser*> KLFLibBasicWidgetFactory::pSchemeGuessers ;
04929