This file is indexed.

/usr/include/klfapp/klflib.h is in libklatexformula3-dev 3.3.0~beta-1+b2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
/***************************************************************************
 *   file klflib.h
 *   This file is part of the KLatexFormula Project.
 *   Copyright (C) 2011 by Philippe Faist
 *   philippe.faist at bluewin.ch
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
/* $Id: klflib.h 881 2014-06-15 21:23:43Z phfaist $ */

#ifndef KLFLIB_H
#define KLFLIB_H

#include <QImage>
#include <QMap>
#include <QUrl>
#include <QDataStream>
#include <QDateTime>
#include <QFileInfo>

#include <klfdefs.h>
#include <klfbackend.h>

#include <klfpobj.h>
#include <klffactory.h>
#include <klfstyle.h>



class KLFProgressReporter;



/** \brief An entry (single formula) in the library
 *
 * Stores Latex code, Date/Time of evaluation, A preview image, A Category String,
 * A Tags String, and a Style in a KLFPropertizedObject-based object.
 *
 * This object can be used as a normal value (ie. it has copy constructor, assignment
 * operator and default constructor).
 */
class KLF_EXPORT KLFLibEntry : public KLFPropertizedObject {
public:
  /** \note The numeric IDs don't have to be preserved from one version of KLF to
   * another, since they are nowhere stored. Properties are always stored by name
   * when dealing in scopes larger than the running application (saved files, etc.).
   */
  enum PropertyId {
    Latex = 0, //!< The Latex Code of the equation
    DateTime, //!< The Date/Time at which the equation was evaluated
    Preview, //!< An Image Preview of equation (scaled down QImage)
    PreviewSize, //!< A cached value of the size of value in \c Preview
    Category, //!< The Category to which eq. belongs (path-style string)
    Tags, //!< Tags about the equation (string)
    Style //!< KLFStyle style used
  };

  KLFLibEntry(const QString& latex = QString(), const QDateTime& dt = QDateTime(),
	      const QImage& preview = QImage(),	const QSize& previewsize = QSize(),
	      const QString& category = QString(), const QString& tags = QString(),
	      const KLFStyle& style = KLFStyle());
  /** This constructor extracts the legacy-style category and tags from latex, and
   * stores latex with those tags stripped. */
  KLFLibEntry(const QString& latex, const QDateTime& dt, const QImage& preview,
	      const KLFStyle& style);
  KLFLibEntry(const KLFLibEntry& copy);
  virtual ~KLFLibEntry();

  inline QString latex() const { return property(Latex).toString(); }
  inline QDateTime dateTime() const { return property(DateTime).toDateTime(); }
  inline QImage preview() const { return property(Preview).value<QImage>(); }
  inline QSize previewSize() const { return property(PreviewSize).value<QSize>(); }
  inline QString category() const { return property(Category).toString(); }
  inline QString tags() const { return property(Tags).toString(); }
  inline KLFStyle style() const { return property(Style).value<KLFStyle>(); }

  inline QString latexWithCategoryTagsComments() const
  { return latexAddCategoryTagsComment(latex(), category(), tags()); }

  inline void setLatex(const QString& latex) { setProperty(Latex, latex); }
  inline void setDateTime(const QDateTime& dt) { setProperty(DateTime, dt); }
  inline void setPreview(const QImage& img) { setProperty(Preview, img); }
  inline void setPreviewSize(const QSize& sz) { setProperty(PreviewSize, sz); }
  /** \note this function normalizes category to remove any double-'/' to avoid empty sections.
   *    Equality between categories can be compared stringwise.
   *
   * See also \ref normalizeCategoryPath(). */
  inline void setCategory(const QString& s) { setProperty(Category, normalizeCategoryPath(s)); }
  inline void setTags(const QString& s) { setProperty(Tags, s); }
  inline void setStyle(const KLFStyle& style) { setProperty(Style, QVariant::fromValue(style)); }

  /** Set the property named \c name to value \c value. If the property does not
   * yet exist in the registered properties, it is registered.
   *
   * \returns -1 for error, or the property ID that was successfully (maybe registered
   * and) set.
   */
  int setEntryProperty(const QString& propName, const QVariant& value);


  /** Parses and returns legacy-style category comment string from latex string
   * in the form <pre>%: Category</pre> */
  static QString categoryFromLatex(const QString& latex);
  /** Parses and returns legacy-style tags comment string from latex string */
  static QString tagsFromLatex(const QString& latex);
  /** Removes legacy-style category and tags comment from latex string */
  static QString stripCategoryTagsFromLatex(const QString& latex);
  /** Creates a latex with category and tags comments */
  static QString latexAddCategoryTagsComment(const QString& latex, const QString& category,
					     const QString& tags);
  /** Renders a category-path "pretty" by removing any double-slashes to single slashes.
   * Trailing slashes are removed. The root category is an empty string.
   *
   * When a category is set to a lib-entry with \c setCategory(), it is automatically
   * normalized.
   *
   * Returned paths may be compared string-wise for equality.
   */
  static QString normalizeCategoryPath(const QString& categoryPath);

private:
  
  void initRegisteredProperties();
};

Q_DECLARE_METATYPE(KLFLibEntry)
  ;

typedef QList<KLFLibEntry> KLFLibEntryList;


//! Contains general definitions to be used anywhere in the KLFLib* framework
namespace KLFLib {
  //! An entry ID
  /** The type of the ID of an entry in a library resource (see \ref KLFLibResourceEngine)
   *
   * \note This type is signed, and may be assigned a negative value. Negative values
   *   should only indicate invalid IDs. Valid IDs are always positive.
   *
   * \note \ref KLFLibResourceEngine::entryId is a typedef of \ref KLFLib::entryId.
   *
   * */
  typedef qint32 entryId;


  /** Describes a matching criterion for a string
   *
   * Note: The Qt::MatchWrap and Qt::MatchRecursive flags are ignored.
   */
  struct StringMatch {
    StringMatch(const QVariant& value = QVariant(), Qt::MatchFlags flags = Qt::MatchExactly)
      : mFlags(flags), mValue(value), mValueString(value.toString()) { }
    StringMatch(const StringMatch& m) : mFlags(m.mFlags), mValue(m.mValue), mValueString(m.mValueString) { }

    /** How the match should be tested (exact match, regex, contains, etc.), this is
     * a binary-OR'ed value of Qt::MatchFlag enum values.
     *
     * the Qt::MatchCaseSensitive may be set to match case sensitive.
     */
    inline const Qt::MatchFlags matchFlags() const { return mFlags; }
    /** The value that will be matched to. */
    inline const QVariant matchValue() const { return mValue; }
    /** equivalent to <tt>matchValue().toString()</tt>, however the conversion is
     * performed once and cached. */
    inline const QString matchValueString() const { return mValueString; }

  protected:
    Qt::MatchFlags mFlags;
    QVariant mValue;
    QString mValueString;
  };

  /** Discribes a matching criterion for the value of a property ID. Although not assumed
   * in this definition, property IDs will eventually refer to KLFPropertizedObject property
   * IDs, more specifically \ref KLFLibEntry property IDs.
   */
  struct PropertyMatch : public StringMatch {
    /** propId is the ID of the property which will have to match as given by \c match */
    PropertyMatch(int propId = -1, const StringMatch& match = StringMatch())
      : StringMatch(match), mPropertyId(propId) { }
    /** copy constructor */
    PropertyMatch(const PropertyMatch& other) : StringMatch(other), mPropertyId(other.mPropertyId) { }

    /** Returns the propery ID set in the constructor. */
    inline int propertyId() const { return mPropertyId; }
    
  protected:
    int mPropertyId;
  };

  /** This is a generalized condition. It can be one of several types.
   *
   * In the future, more match condition types may be added. For now, the following
   * matching condition types are supported.
   *  - property string matching (see \ref PropertyMatch)
   *  - AND of N conditions
   *  - OR of N conditions
   *
   * This class is meant for use with findEntries().
   */
  struct EntryMatchCondition
  {
    enum Type {
      MatchAllType = 0, //!< Matches all entries
      PropertyMatchType, //!< Matches a property ID with a string (with a \ref StringMatch)
      NegateMatchType, //!< Matches entries that don't match a condition
      OrMatchType, //!< entries have to match with one of a list of conditions
      AndMatchType //!< entries have to match with all given conditions
    };

    //! Get which type of condition this is
    inline Type type() const { return mType; }
    //! Relevant for type PropertyMatchType
    inline PropertyMatch propertyMatch() const { return mPropertyMatch; }
    //! Relevant for types OrMatchType and AndMatchType
    inline QList<EntryMatchCondition> conditionList() const { return mConditionList; }

    static EntryMatchCondition mkMatchAll();
    static EntryMatchCondition mkPropertyMatch(PropertyMatch pmatch);
    /** Stores \c condition in first element of conditionList(). */
    static EntryMatchCondition mkNegateMatch(const EntryMatchCondition& condition);
    static EntryMatchCondition mkOrMatch(QList<EntryMatchCondition> conditions);
    static EntryMatchCondition mkAndMatch(QList<EntryMatchCondition> conditions);

  protected:
    EntryMatchCondition(Type type) : mType(type) { }

    Type mType;

    PropertyMatch mPropertyMatch;
    QList<EntryMatchCondition> mConditionList;
  };

}

//! Utility class for sorting library entry items
/**
 * This class can be used as a sorter to sort entry items.
 *
 * This class functions as follows:
 * - operator()() calls compareLessThan() with the stored propId() and order().
 * - \ref compareLessThan() in turns calls entryValue() to get string representations of the
 *   values of the property to compare for each entry, and compares the strings with
 *   \ref QString::localeAwareCompare().
 * - \ref entryValue() provides sensible string representations for the given property in the
 *   given entry.
 *
 * \note The column number may be set to be equal \c -1, to indicate an invalid sorter (maybe
 *   to indicate that a list should not be sorted). However, the functions \ref entryValue(),
 *   \ref compareLessThan() and operator()() are NOT meant to be used with an invalid \c propId.
 *   In other words, if isValid() is false (or equivalently, if \ref propId() is negative), don't
 *   attempt any sorting or comparisions.
 *
 * To customize the behaviour of this class, you may subclass it and reimplement any level
 * of its behavior, eg. you may want to just reimplement entryValue() to alter the string
 * representation of the values of some properties, or you could reimplement compareLessThan()
 * to do more sophisticated comparisions.
 *
 * \note There is no copy constructor. If there was, there would be no way of customizing the sort
 *   behavior. To use the entry sorter in contexts where you need to copy an object, use the
 *   clone mechanism with the clone constructor. (Although this should scarcely be needed ...).
 */
class KLF_EXPORT KLFLibEntrySorter
{
public:
  KLFLibEntrySorter(int propId = -1, Qt::SortOrder order = Qt::AscendingOrder);
  /** Used to "circumvent" the copy-constructor issues of reimplemented functions.
   * If an object is constructed using this constructor all calls to entryValue(),
   * compareLessThan(), and operator()() are redirected to clone's.
   *
   * Calls to setPropId() and setOrder() will fail and emit a warning.
   *
   * In particular, never pass 'this' nor 'NULL' as clone!
   */
  KLFLibEntrySorter(const KLFLibEntrySorter *clone);
  virtual ~KLFLibEntrySorter();

  inline bool isValid() const { return (pPropId >= 0); }

  //! The currently set property that will be queried in the items we're sorting
  inline int propId() const { return pPropId; }
  //! The currently set sorting order
  inline Qt::SortOrder order() const { return pOrder; }

  //! Set the KLFLibEntry property id the sort will take into account
  virtual void setPropId(int propId);
  //! Set the sort order
  virtual void setOrder(Qt::SortOrder order);

  //! Returns a string representation of the given property in the given entry
  virtual QString entryValue(const KLFLibEntry& entry, int propId) const;

  //! Compares entries two entries according to the given property and order
  /** Compares the given property of entries \c a and \c b.
   *
   * When \c order is \c Qt::Ascending, if \c a is found to be less than (and not equal) to
   * \c b, then TRUE is returned, otherwise FALSE is returned.
   *
   * If the \c order is \c Qt::Descending, if \c b is found to be less than (and not equal) to
   * \c a, then TRUE is returned, otherwise FALSE is returned.
   */
  virtual bool compareLessThan(const KLFLibEntry& a, const KLFLibEntry& b,
			       int propId, Qt::SortOrder order) const;

  /** This is a wrapper that calls \ref compareLessThan() with the previously set
   * propId() and order().
   */
  virtual bool operator()(const KLFLibEntry& a, const KLFLibEntry& b) const;


private:
  const KLFLibEntrySorter * pCloneOf;

  int pPropId;
  Qt::SortOrder pOrder;
};



/** \brief An abstract resource engine
 *
 * This class is the base of all resource types. Subclasses (e.g. KLFLibDBEngine) implement
 * the actual access to the data, while this class defines the base API that will be used
 * by e.g. the library browser (through a KLFAbstractLibView subclass) to access the data.
 *
 * Subclasses may choose to implement various features specified by the \ref ResourceFeature
 * enum. The supported features must be passed (binary OR-ed) to the constructor.
 *
 * Library resources provide entries without any particular order.
 *
 * Library entries are communicated with KLFLibEntry objects. Each entry in the resource must
 * be attributed a numerical ID, which is unique within the resource, in particular not
 * necessarily globally unique among all open resources. For engines implementing the
 * \ref FeatureSubResources feature, the attributed IDs have only to be unique within the
 * sub-resource the entry lives in.
 *
 * Entries are queried by calling for example the functions: \ref allEntries(), \ref entries(),
 * \ref entry(). See the individual function documentation for more details.
 *
 * The API in this class for accessing data is pretty elaborate. You may consider to subclass
 * \ref KLFLibResourceSimpleEngine, which requires you to implement a simpler API, but at the
 * price of not being able to take profit of the optimization opportunities given by the
 * more complicated API.
 *
 * <b>Resource Properties</b>. Resources have properties (stored in a
 * KLFPropertizedObject structure, NOT in regular QObject
 * properties) that ARE STORED IN THE RESOURCE DATA ITSELF. Built-in properties are listed
 * in the \ref ResourceProperty enum. Some properties may be implemented read-only
 * (eg. \ref PropAccessShared) in which case saveResourceProperty() should return FALSE.
 *
 * The view used to display this resource is stored in the "ViewType" resource property (and
 * thus should be stored in the backend data like other properties).
 *
 * <b>Note on URL</b>. The URL is not a resource property as it is not stored in the resource
 * itself. However the resource engine instance knows about the url it is manipulating
 * (because subclasses pass the relevant url as parameter in the constructor). However, the
 * URL itself blindly stored and reprovided when requested; it is not used by
 * KLFLibResourceEngine itself. Small exception: in the constructor, some query items are
 * recognized and stripped from the URL. See below.
 *
 * <b>Read-Only Mode</b>. The read-only mode differs from the locked property in that the
 * mode is activated by the accessor only and is NOT stored in the resource data eg. on disk
 * (in contrast to the locked property). It is up to SUBCLASSES to enforce this flag and
 * prevent data from being modified if isReadOnly() is TRUE.<br>
 * Subclasses may prevent read-only mode by not specifying
 * the FeatureReadOnly in the constructor. In this case the default implementation of
 * \ref setReadOnly() will return FALSE without doing anything. Also in this case, any
 * occurrence of the query item "klfReadOnly" in the URL is stripped and ignored.
 *
 * <b>Sub-Resources</b>. Sub-resources are a way of logically separating the contents of
 * a resource into separate so-called "sub-resources", like for example a library could
 * contain a sub-resource "History", "Archive" etc. Derived subclasses don't have to
 * implement subresources, they can specify if subresources are available using the
 * FeatureSubResources flag in the constructor. In classes implementing sub-resources,
 * the <i>default sub-resource</i> (queried by \ref defaultSubResource() and set by
 * \ref setDefaultSubResource()) is the resource that the \ref insertEntry(),
 * \ref changeEntries(), etc.
 * family functions will access when the variant of the function without sub-resource
 * argument is called.
 *
 * <b>Sub-Resource Properties</b>. Sub-resources, when implemented by the subclass, may
 * each have properties (the API would suggest subclasses to store these property values
 * into \ref KLFPropertizedObject's). The properties (structure+values) are NOT stored
 * by KLFLibResourceEngine itself, all the work must be done by the subclass, in particular
 * reimplementing \ref subResourceProperty() and \ref setSubResourceProperty(). Again this
 * feature is implemented by the subclass if and only if the subclass specified
 * \ref FeatureSubResourceProps in the constructor argument. In this case note also that views
 * may for example expect the resource to provide values for the sub-resource properties defined
 * by \ref SubResourceProperty.
 *
 * <b>query Items in URL</b>. The URL may contain query items e.g.
 * <tt>scheme://klf.server.dom/path/to/location<b>?klfReadOnly=true</b></tt>. Here is a
 * list of recognized (universal) query items. Subclasses may choose to recognize more query
 * items, but these listed here are detected in the KLFLibResourceEngine constructor and
 * the appropriate flags are set (eg. \ref isReadOnly()):
 * - <tt>klfReadOnly=</tt>{<tt>true</tt>|<tt>false</tt>} If provided, sets the read-only
 *   flag to the given value. If not provided, the flag defaults to false (flag is directly
 *   set, bypassing the setReadOnly() function).
 * - <tt>klfDefaultSubResource=<i>sub-resource name</i></tt> If provided, specifies which
 *   sub-resource (which has to be present in the given location) should be opened by default.
 *   See \ref setDefaultSubResource().
 * .
 * Note that recognized query items (and <i>only</i> the query items recognized at the
 * KLFLibResourceEngine level) are stripped from the \ref url() as they are parsed. Subclasses
 * may choose to (independently) recognize and strip other query items from URL if it is relevant
 * to do so.
 *
 * <b>NOTES FOR SUBCLASSES</b><br>
 * - Subclasses must deal with the properties and implement them as they are meant to, and
 *   as they have been documented in their respective functions (see \ref locked(), \ref title()).
 *   For example, if a resource is \ref locked(), then \ref canModifyData() and \ref canModifyProp()
 *   must return FALSE and any attempt to modify the resource must fail.
 * - Subclasses must reimplement \ref saveResourceProperty() to save the new property value
 *   to the backend data, or return FALSE to cancel the resource change. Calls to
 *   \ref setLocked(), \ref setTitle() or setViewType() all call in turn \ref setResourceProperty(),
 *   the default implementation of which is usually sufficient, which calls in turn
 *   \ref saveResourceProperty().
 * - See also docs for \ref setResourceProperty() and \ref saveResourceProperty().
 * - The \ref resourcePropertyChanged() is emitted in the default implementation of
 *   \ref setResourceProperty().
 * - lengthy operations should emit the signal \ref operationStartReportingProgress() with a suitable
 *   KLFProgressReporter as necessary to inform callers of progress of operations that can take some
 *   time. This is recommended, but subclasses aren't forced to comply (for laziness' sake for ex...).
 *   However, subclasses should test ONCE per operation whether \ref thisOperationProgressBlocked() and
 *   should not emit progress in that case.
 */
class KLF_EXPORT KLFLibResourceEngine : public QObject, public KLFPropertizedObject
{
  Q_OBJECT
public:
  typedef KLFLib::entryId entryId;
  
  //! A KLFLibEntry in combination with a KLFLib::entryId
  struct KLFLibEntryWithId {
    KLFLibEntryWithId(entryId i = -1, const KLFLibEntry& e = KLFLibEntry())
      : id(i), entry(e) { }
    entryId id;
    KLFLibEntry entry;
  };

  /** List of built-in KLFPropertizedObject-properties. See
   * \ref KLFLibResourceEngine "class documentation" and \ref setResourceProperty(). */
  enum ResourceProperty {
    PropTitle = 0,
    PropLocked,
    PropViewType,
    PropAccessShared
  };

  /** List of pre-defined properties that can be applied to sub-resources when the features
   * \ref FeatureSubResources and \ref FeatureSubResourceProps are implemented. See also
   * \ref setSubResourceProperty().
   *
   * \note These properties, by contrast to resource properties, have fixed numerical IDs, since
   *   sub-resource properties are not backed by a KLFPropertizedObject object. */
  enum SubResourceProperty {
    SubResPropTitle    = 0,
    SubResPropLocked   = 1,
    SubResPropViewType = 2
  };

  //! Features that may or may not be implemented by subclasses
  /** These binary codes specify features that a subclass may or may not implement.
   *
   * The subclass provides the binary combination of the exact features it supports in the
   * constructor argument in \ref KLFLibResourceEngine().
   *
   * The flags can be accessed with a call to \ref supportedFeatureFlags(). They cannot be
   * modified after the constructor call.
   *
   * See this \ref KLFLibResourceEngine "class documentation" for more details.
   */
  enum ResourceFeature {
    //! Open in Read-Only mode
    /** Flag indicating that this resource engine supports opening a location in read-only mode.
     * This resource explicitely checks that we're not \ref isReadOnly() before modifying the
     * resource contents. */
    FeatureReadOnly		= 0x0001,
    //! Lock the resource
    /** Flag indicating that this resource engine supports the resource property \ref PropLocked,
     * can modify that property and checks that we're not \ref locked() before modifying the
     * resource contents.
     *
     * Resources supporting feature \ref FeatureSubResourceProps, in combination with this feature
     * (FeatureLocked) are also expected to treat properly locked sub-resources (ie. sub-resource
     * property \ref SubResPropLocked). */
    FeatureLocked		= 0x0002,
    //! Implements the \ref saveTo() function
    /** Flag indicating that this resource engine implements the saveTo() function, ie. that
     * calling it has a chance that it will not fail */
    FeatureSaveTo		= 0x0004,
    //! Data can be stored in separate sub-resources
    /** Flag indicating that this resource engine supports saving and reading data into different
     * "sub-resources". See \ref KLFLibResourceEngine "class documentation" for details. */
    FeatureSubResources		= 0x0008,
    //! Sub-Resources may be assigned properties and values
    /** Flag indicating that this resource engine supports saving and reading sub-resource
     * property values. This flag makes sense only in combination with \c FeatureSubResources.
     * Note that views may assume that implementing sub-resource properties means also providing
     * sensible values and/or loaded/stored values for the built-in sub-resource properties
     * described in the \ref SubResourceProperty enum. */
    FeatureSubResourceProps	= 0x0010
  };

  /**
   *
   * \note If the URL \c url needs to be normalized in some way (eg. convert some query item
   * values to lower case, ...), then you need to implement a static function, eg.
   * \code
   * static KLFMyEngine * openURL(const QUrl& url) {
   *   QUrl normalized = url;
   *   // ... normalize URL ...
   *   return new KLFMyEngine(normalized, ...);
   * }
   * KLFMyEngine::KLFMyEngine(const QUrl& url, ...) : KLFLibResourceEngine(url,...)
   * {
   *   // ...
   * }
   * \endcode
   * which will pass the normalized URL here. You cannot change the URL once it has been
   * passed to the constructor. Note however that the stored URL has some elements stripped,
   * as described in the class documentation \ref KLFLibResourceEngine, which you can
   * change via the API (eg. setDefaultSubResource()).
   */
  KLFLibResourceEngine(const QUrl& url, uint supportedfeatureflags, QObject *parent = NULL);

  virtual ~KLFLibResourceEngine();

  //! List of features supported by this resource engine
  /** Use this function to probe whether this resource instance supports a specific
   * feature. For example a property editor widget might want to know if this resource
   * supportes the \ref FeatureLocked feature, to enable or disable the corresponding
   * check box.
   *
   * Do not reimplement in subclasses, simply pass the feature flags to the constructor.
   * */
  virtual uint supportedFeatureFlags() const { return pFeatureFlags; }

  //! Format options one can give to \ref url()
  enum WantUrlFormatFlag {
    //! Add a query item for default sub-res. as \c "klfDefaultSubResource"
    WantUrlDefaultSubResource = 0x01,
    //! Add a query item for read-only status, as \c "klfReadOnly"
    WantUrlReadOnly = 0x02
  };
  //! query URL
  /** Returns the identifying URL of this resource.
   *
   * \note This is not quite the URL passed to the constructor. Some query items are recognized
   *   and stripped. See the \ref KLFLibResourceEngine "Class Documentation" for more information.
   *
   * Flags may be specified as to which query items we would like to add to URL (eg. default
   * sub-resource, read-only status). see \ref WantUrlFormatFlag.
   *
   * See also \ref KLFAbstractLibView::url(). That function gives also information on what part
   * of the resource it displays.
   */
  virtual QUrl url(uint flags = 0x0) const;

  //! Compare this resource's URL with another's
  /** Compares the URL of this resource with \c other, and returns a binary OR'ed value of
   * KlfUrlCompareFlag enum values of tests that have proved true (see KlfUrlCompareFlag
   * for a list of URL-comparision tests in klfutil.h in klftools).
   *
   * This function should return the following flag, if its corresponding tests turn out
   * to be true. This function should NOT return any other flag that is not listed here.
   * - \c KLFUrlComapreBaseEqual should be set if this resource shares its data with the resource
   *   given by URL \c other. Default sub-resources are to be ignored.
   * 
   * The \c interestFlags is a binary OR'ed value of KlfUrlCompareFlag values of tests
   * to be performed. Any flag that is set in \c interestFlags indicates that the return
   * value of this function, when binary-AND'ed with that flag, is the result (T or F)
   * of the test the flag stands for. However, if a flag is not set in \c interestFlags,
   * its state in the return value by this function is undefined.
   *
   * See also klfUrlCompare().
   */
  virtual uint compareUrlTo(const QUrl& other, uint interestFlags = 0xfffffff) const = 0;

  //! query read-only state
  /** See \ref KLFLibResourceEngine "Class Documentation" for more details. */
  virtual bool isReadOnly() const { return pReadOnly; }

  //! The human-set title of this resource
  /** See \ref setTitle(). */
  virtual QString title() const { return KLFPropertizedObject::property(PropTitle).toString(); }

  //! Is this resource is locked?
  /** If the resource is locked (property \ref PropLocked), no changes can be in principle made,
   * except <tt>setLocked(false)</tt> (of course...).
   *
   * Note: the subclass is responsible to check in functions such as insertEntry(), that the
   * resource is not locked and not read-only etc. (checked all-in-one with \ref canModifyData()).
   *
   * The default implementation has some limited support for the locked property: see
   * \ref setLocked(). */
  virtual bool locked() const { return KLFPropertizedObject::property(PropLocked).toBool(); }

  //! The (last) View Type used to display this resource
  virtual QString viewType() const
  { return KLFPropertizedObject::property(PropViewType).toString(); }

  //! If the resource is accessed by many clients
  /** Whether the resource is meant to be shared by many clients (eg. a remote database access)
   * or if it is local and we're the only one to use it (eg. a local sqlite file).
   *
   * This property may be used by views to decide if they can store meta-information about the
   * view state in the resource itself (icon positions in icon view mode for example). */
  virtual bool accessShared() const
  { return KLFPropertizedObject::property(PropAccessShared).toBool(); }

  //! Get the value of a resource property
  /** Returns the value of the given resource property. If the property is not registered,
   * returns an invalid QVariant with a warning.
   *
   * For built-in resource properties, consider using the simpler \ref locked(), \ref title()
   * and \ref viewType() methods (for example). */
  virtual QVariant resourceProperty(const QString& name) const;

  enum ModifyType {
    AllActionsData = 0,
    UnknownModification = 0,
    InsertData,
    ChangeData,
    DeleteData
  };

  /** Returns TRUE here if it is possible to modify the resource's data in the way described
   * by \c modifytype (see \ref ModifyType enum).
   *
   * Engines supporting feature \ref FeatureSubResources should return TRUE or FALSE whether
   * it is possible to perform the requested action in the given sub-resource \c subResource.
   * Other engines should ignore the \c subResource parameter.
   *
   * For engines supporting all of \ref FeatureSubResources, \ref FeatureSubResourceProps, and
   * \ref FeatureLocked the default implementation checks whether the sub-resource is locked
   * by querying \ref subResourceProperty(\ref SubResPropLocked).
   *
   * \c modifytype must be one of AllActionsData, InsertData, ChangeData, DeleteData.
   *
   * The base implementation returns TRUE only if the current resource is not read-only (see
   * \ref isReadOnly()) and is not locked (see \ref locked()). Subclasses should reimplement
   * this function to add more sophisticated behaviour, eg. checking that an open file is not
   * read-only, or that a DB user was granted the correct rights, etc.
   *
   * \warning subclasses should call the base implementation to e.g. take into account
   * eg. the \ref locked() property. If the base implementation returns FALSE, then the
   * subclasses should also return FALSE. */
  virtual bool canModifyData(const QString& subResource, ModifyType modifytype) const;

  /** This function is provided for convenience for resource not implementing
   * \ref FeatureSubResources, or Views relying on the default sub-resource.
   *
   * \warning Subclasses should normally not reimplement this function, but rather the
   *   canModifyData(const QString&, ModifyType) function, even if they do not support
   *   sub-resources!
   *
   * The default implementation of this function (which should be sufficient in a vast majority
   * of cases) calls
   * \code
   *  canModifyData(defaultSubResource(), modifytype)
   * \endcode
   * as one would expect.
   */
  virtual bool canModifyData(ModifyType modifytype) const;

  /** Subclasses should return TRUE here if it is possible to modify the resource's property
   * identified by \c propId. Return for ex. false when opening a read-only file.
   *
   * \warning subclasses should call the base implementation to e.g. take into account
   * the \ref locked() property and \ref isReadOnly() state. If the base implementation
   * returns FALSE, then the subclasses should also return FALSE.
   *
   * If \c propId is negative, then a more general "Can we generally speaking modify properties
   * right now?" is returned.
   *
   * \note The base implementation returns TRUE if the resource is locked but if \c propId is
   * \ref PropLocked (to be able to un-lock the resource!) */
  virtual bool canModifyProp(int propId) const;

  /** Subclasses should return TRUE if they can handle a new resource property that they
   * (maybe) haven't yet heard of, and if they can handle saving and loading the property
   * as a \ref QVariant to and from the backend data.
   * 
   * Call \ref loadResourceProperty() to actually register the property and save a value
   * to it. */
  virtual bool canRegisterProperty(const QString& propName) const;

  /** Suggested library view widget to view this resource with optimal user experience :-) .
   * Return QString() for default view. */
  virtual QString suggestedViewTypeIdentifier() const { return QString(); }

  /** Returns TRUE if this resource supports sub-resources and contains a sub-resource
   * named \c subResource.
   *
   * The default implementation checks that the \ref FeatureSubResources is supported, and
   * that \ref subResourceList() contains \c subResource (with exact string match).
   *
   * If subclasses have a more optimized method to check this, they may (but need not
   * necessarily) reimplement this function to optimize it.
   *
   * Engines that have case-insensitive resource names (eg. SQL tables) must reimplement
   * this function to do a case-insensitive test.
   */
  virtual bool hasSubResource(const QString& subResource) const;

  /** Returns a list of sub-resources in this resource. This function is relevant only
   * if the \ref FeatureSubResources is implemented. */
  virtual QStringList subResourceList() const { return QStringList(); }

  /** Returns the default sub-resource, ie. the sub-resource to access if eg. the variant
   * of insertEntry() without the sub-resource argument is called.
   *
   * This is relevant only if the engine supports feature \ref FeatureSubResources.
   */
  virtual QString defaultSubResource() const;

  /** \brief Compare our sub-resource name to another
   *
   * Returns TRUE if our default sub-resource name equals \c subResource, FALSE otherwise.
   *
   * The default implementation tests for string equality (case sensitive). If sub-resources
   * in the reimplemented engine are case-insensitive, then reimplement this function to
   * compare string case-insensitive.
   */
  virtual bool compareDefaultSubResourceEquals(const QString& subResourceName) const;

  /** Returns TRUE if we can create a new sub-resource in this resource.
   *
   * This function can be reimplemented if the resource supports feature \ref FeatureSubResources.
   *
   * The default implementation returns FALSE.
   */
  virtual bool canCreateSubResource() const;

  /** Returns TRUE if we can give the sub-resource \c subResource a new name. More specifically,
   * returns TRUE if \ref renameSubResource() on that sub-resource has chances to succeed.
   *
   * This function can be reimplemented if the resource supports feature \ref FeatureSubResources.
   *
   * The default implementation returns FALSE.
   */
  virtual bool canRenameSubResource(const QString& subResource) const;

  /** Returns TRUE if we can completely delete sub-resource \c subResource from the resource.
   *
   * If this function returns FALSE, a subsequent call to deleteSubResoruce() is certain
   * to fail.
   *
   * The default implementation returns FALSE.
   */
  virtual bool canDeleteSubResource(const QString& subResource) const;

  /** Queries properties of sub-resources. The default implementation returns an empty
   * QVariant(). Test the \ref supportedFeatureFlags() for \ref FeatureSubResourceProps to
   * see if this feature is implemented. In particular, subclasses should specify whether
   * they implement this feature by passing the correct feature flags. */
  virtual QVariant subResourceProperty(const QString& subResource, int propId) const;

  /** Returns a list of sub-resource properties that are supported by this resource.
   *
   * This function makes sense to be reimplemented and called only if this resource supports
   * features \ref FeatureSubResources and \ref FeatureSubResourceProps.
   *
   * The default implementation returns an empty list.
   */
  virtual QList<int> subResourcePropertyIdList() const { return QList<int>(); }

  /** Returns a property name for the sub-resource property \c propId.
   *
   * The name should be significant but machine-compatible (in particular, NOT translated) as
   * it could be used to identify the property for example to save it possibly...
   *
   * the default implementation returns reasonable names for \c SubResPropTitle,
   * \c SubResPropLocked, and \c SubResPropViewType, and returns the \c propId in a string
   * for other IDs (\ref QString::number()).
   *
   * This function makes sense to be called only for engines supporting
   * \ref FeatureSubResourceProps.
   */
  virtual QString subResourcePropertyName(int propId) const;

  /** Returns TRUE if the property \c propId in sub-resource \c subResource can be modified.
   *
   * This function should not be called or reimplemented for classes not supporting feature
   * \ref FeatureSubResourceProps.
   *
   * The default implementation provides a basic functionality based on \ref baseCanModifyStatus().
   * If the modifiable status of the sub-resource \c subResource is \ref MS_CanModify, or if the
   * status is \ref MS_IsLocked but the \c propId we want to modify is \ref SubResPropLocked, this
   * function returns TRUE. In other cases it returns FALSE.
   *
   * In short, it behaves as you would expect it to: protect against modifications but allow
   * un-locking of a locked sub-resource.
   */
  virtual bool canModifySubResourceProperty(const QString& subResource, int propId) const;

  //! query an entry in this resource
  /** Returns the entry (in the sub-resource \c subResource) corresponding to ID \c id, or an
   * empty KLFLibEntry() if the \c id is not valid.
   *
   * \note Subclasses must reimplement this function to behave as described here.
   *
   * For resources implementing \ref FeatureSubResources, the \c subResource argument specifies
   * the sub-resource in which the entry should be fetched. Classes not implementing this feature
   * should ignore this parameter.
   *  */
  virtual KLFLibEntry entry(const QString& subResource, entryId id) = 0;

  //! query an entry in this resource
  /** Returns the entry (for classes implementing the \ref FeatureSubResources, queries the default
   * sub-resource) corresponding to ID \c id, or an empty KLFLibEntry() if the \c id is not valid.
   *
   * The default implementation calls \ref entry(const QString& subResource, entryId id) with
   * the default subresource as argument. See \ref setDefaultSubResource().
   */
  virtual KLFLibEntry entry(entryId id);

  //! query the existence of an entry in this resource
  /** Returns TRUE if an entry with entry ID \c id exists in this resource, in the sub-resource
   * \c subResource, or FALSE otherwise.
   *
   * \note Subclasses must reimplement this function to behave as described here.
   */
  virtual bool hasEntry(const QString& subResource, entryId id) = 0;

  //! query the existence of an entry in this resource
  /** Returns TRUE if an entry with entry ID \c id exists in this resource or FALSE otherwise.
   * Classes implementing the \ref FeatureSubResources will query the default sub-resource, see
   * \ref setDefaultSubResource().
   *
   * The default implementation calls \ref hasEntry(const QString& subResource, entryId id) with
   * the default subresource as argument. See \ref setDefaultSubResource().
   */
  virtual bool hasEntry(entryId id);

  //! query multiple entries in this resource
  /** Returns a list of \ref KLFLibResourceEngine::KLFLibEntryWithId "KLFLibEntryWithId" s, that
   * is a list of KLFLibEntry-ies with their corresponding IDs, exactly corresponding to the
   * requested entries given in idList. The same order of entries in the returned list as in the
   * specified \c idList is garanteed. For classes implementing sub-resources
   * (\ref FeatureSubResources), the sub-resource \c subResource is queried.
   *
   * The KLFLibEntry objects are populated only of the required \c wantedEntryProperties, which is
   * a list of IDs of KLFLibEntry properties (the KLFPropertizedObject-kind properties) that are
   * set in the KLFLibEntry object. The other fields are left undefined. If the property
   * list is empty (by default), then all properties are fetched and set.
   *
   * If in the list an ID is given which does not exist in the resource, a corresponding
   * KLFLibEntryWithId entry is returned in which the \c entry is set to an empty \c KLFLibEntry()
   * and the \c id is set to \c -1.
   *
   * If \c idList is empty, then this function returns an empty list.
   *
   * \note Subclasses must reimplement this function to behave as described here.
   * */
  virtual QList<KLFLibEntryWithId> entries(const QString& subResource,
					   const QList<KLFLib::entryId>& idList,
					   const QList<int>& wantedEntryProperties = QList<int>()) = 0;

  //! query multiple entries in this resource
  /** Returns a list of \ref KLFLibEntryWithId's, that is a list of KLFLibEntry-ies with their
   * corresponding IDs, exactly corresponding to the requested entries given in idList. The same
   * order of entries in the returned list as in the specified \c idList is garanteed. For classes
   * implementing sub-resources (\ref FeatureSubResources), the default sub-resource is
   * queried, see \ref setDefaultSubResource().
   *
   * The KLFLibEntry objects are populated only of the required \c wantedEntryProperties, which is
   * a list of IDs of KLFLibEntry properties (the KLFPropertizedObject-kind properties) that are
   * set in the KLFLibEntry object. The other fields are left undefined. If the property
   * list is empty (by default), then all properties are fetched and set.
   *
   * If in the list an ID is given which does not exist in the resource, a corresponding
   * KLFLibEntryWithId entry is returned in which the \c entry is set to an empty \c KLFLibEntry()
   * and the \c id is set to \c -1.
   *
   * If \c idList is empty, then this function returns an empty list.
   *
   * The default implementation calls
   * \ref entries(const QString& subResource, const QList<KLFLib::entryId>& idList, const QList<int>&)
   * with the default subresource as argument. See \ref setDefaultSubResource().
   */
  virtual QList<KLFLibEntryWithId> entries(const QList<KLFLib::entryId>& idList,
					   const QList<int>& wantedEntryProperties = QList<int>());


  /** \brief A structure that describes a query for query()
   *
   * The following properties should be adjusted (by direct access) before calling query().
   *
   * \c matchcondition is an \ref KLFLib::EntryMatchCondition struct that tells which properties have to be
   * matched, how, and to what value. Only entries that match the match condition set in \c query will
   * be returned by query(). Note that the match condition itself may be a complex condition, like an OR
   * and AND tree of property matching conditions with strings or regexps. See \ref KLFLib::EntryMatchCondition,
   * and \ref KLFLib::PropertyMatch for more info. The idea is that engines can translate such conditions into,
   * eg. a SQL WHERE condition for optimized entry queries.
   *
   * The default match condition (set automatically in constructor) matches all entries.
   *
   * The first \c skip results will be ignored, and the first returned result will be the <tt>skip</tt>'th
   * entry (that is counting from 0; or the <tt>skip+1</tt>'th, counting more intuitively from 1). By default,
   * \c skip is zero, so no entries are skipped. The entries must be skipped \a after they have been sorted.
   * The query() function's return value (entry count) does not include the skipped entries.
   *
   * A \c limit may be set to limit the number of returned results (default is \c -1, meaning no limit).
   *
   * \c orderPropId specifies along which KLFLibEntry property ID the items should be ordered. This
   * can be \c -1 to specify that elements should not be ordered; their order will then be undefined.
   * Default value: \c -1.
   *
   * \c orderDirection specifies in which direction the elements should be ordered. This can be
   * Qt::AscendingOrder or Qt::DescendingOrder (lesser value first or greater value first).
   *
   * \c wantedEntryProperties is a list of properties the lists should be filled with. Elements in the
   * entryWithIdList and rawEntryList lists will only have those properties listed in
   * \c wantedEntryProperties set. The other properties are undefined (some implementations may decide
   * to ignore this optimization). An empty list (which is the default) indicates that all entry
   * properties have to be set.
   */
  struct Query
  {
    /** Default constructor. sets reasonable default values as documented in class doc. */
    Query()
      : matchCondition(KLFLib::EntryMatchCondition::mkMatchAll()),
	skip(0),
	limit(-1),
	orderPropId(-1),
	orderDirection(Qt::AscendingOrder),
	wantedEntryProperties(QList<int>())
    {
    }

    KLFLib::EntryMatchCondition matchCondition;
    int skip;
    int limit;
    int orderPropId;
    Qt::SortOrder orderDirection;
    QList<int> wantedEntryProperties;
  };

  /** \brief A structure that will hold the result of a query() query.
   *
   * This class will contain the entry ID list, the raw entry list and the entry-with-id
   * list of the entries that matched the query() query this object was given to.
   *
   * \c fillFlags may specify which of the aforementioned lists are to be filled (those that are
   * not needed by the caller don't have to be filled, this saves time). You may pass those flags
   * to the constructor.
   *
   * Once the \c fillFlags adjusted, pass a pointer to this object to the query() function to
   * retrieve results.
   *
   * \warning The lists in this object are not garanteed to be cleared at the beginning of
   *   query(). If you recycle this object to call query() a second time, be sure to clean this
   *   object first.
   */
  struct QueryResult
  {
    enum Flags { FillEntryIdList = 0x01, FillRawEntryList = 0x02, FillEntryWithIdList = 0x04 };

    /** Constructor. Sets \c fillFlags as given, and sets reasonable default values for the other
     * members. */
    QueryResult(uint fill_flags = 0x00)  : fillFlags(fill_flags)   {  }
    uint fillFlags;

    QList<KLFLib::entryId> entryIdList;
    KLFLibEntryList rawEntryList;
    QList<KLFLibEntryWithId> entryWithIdList;
  };


  //! query entries in this resource with specified property values
  /** Returns a list of all entries in this resource (and in sub-resource \c subResource
   * for the engines supporting this feature) that match all the required matches specifed
   * in \c matchcondition.
   *
   * \note the subclass is responsible for providing a functional implementation of this function.
   *   Subclasses that don't want to pass much time to implement this feature can resort to calling
   *   the static method \ref KLFLibResourceSimpleEngine::queryImpl() that provides a functional
   *   (but not very optimized) default implementation; the
   *   KLFLibResourceSimpleEngine::testMatchConditionImpl() function may prove useful for testing match
   *   conditions; and the utilities KLFLibEntrySorter and KLFLibResourceSimpleEngine::QueryResultListSorter
   *   might prove useful for sorting entries in conjuction with qLowerBound().
   *
   * \c query is a \ref Query object that describes the query. See \ref Query for details.
   *
   * \c result is a \ref QueryResult structure that will be filled with the queried data. See
   * \ref QueryResult for details.
   *
   * The matches are returned in the following way into the \c result structure:
   *   - if the appropriate flag in \c result is set, then <tt>result.entryIdList</tt> is set to a list
   *     of all entry IDs that matched
   *   - if the appropriate flag in \c result is set, then <tt>result.rawEntryList</tt> is set to a list
   *     of all entries that matched, stored as KLFLibEntry objects. Only the requested properties
   *     are populated (specified by <tt>query.wantedEntryProperties</tt>)
   *   - if the appropriate flag in \c result is set, then <tt>result.entryWithIdList</tt> is set
   *     to a list of all entries, with their corresponding entry ID, that matched (similar to the
   *     return value of allEntries()). Only the requested properties are populated (as specified
   *     by <tt>result.wantedEntryProperties</tt>.)
   *
   * If the \c orderPropId member in \c query is not \c -1, then the returned results (in all
   * to-be-filled lists) are ordered according to the entry property ID \c orderPropId, in the order
   * specified by \c orderDirection.
   *
   * \returns the number of items in the resource that matched. If a \c limit was set in \c query,
   *   then at most that many results are returned. \c 0 is returned if no match was found. \c -1
   *   can be returned to signify an error (eg. invalid regexp, i/o error, etc.).
   *
   * The KLFLibEntry objects are populated only of the required \c wantedEntryProperties as set in
   * \c query (see \ref Query), which is a list of IDs of KLFLibEntry properties (the
   * KLFPropertizedObject-kind properties) that are set in the KLFLibEntry object. If the property
   * list is empty (by default), then all properties are fetched and set. Note that if this list
   * is not empty, then the properties not in the list are undefined: they may be uninitialized,
   * set to null/invalid, or filled eg. by an implementation that ignores \c wantedEntryProperties.
   *
   * \note it is possible to specify a property ID in the match condition that isn't given in
   *   \c wantedEntryProperties, and reimplementations must handle this. <i>Reason: even if
   *   this may seem inconsistent, it can be easily implemented in some examples of engines (SQL
   *   condition, ...) and can easily be worked around in other engines by adding the requested
   *   property to the wanted property list. Example: listing entries by date/time order, without
   *   necessarily displaying the date/time.</i>
   */
  virtual int query(const QString& subResource, const Query& query, QueryResult *result) = 0;


  /** \brief List all distinct values that a property takes in all entries
   *
   * \return A list of all (distinct) values that a given property in all the entries of sub-resource
   *   \c subResource takes.
   *
   * For example, KLFLibModel uses this function in category tree mode to get the category tree,
   * by passing \ref KLFLibEntry::Category as \c entryPropId.
   *
   * The order of the elements within the returned list is not defined.
   *
   * In mathematical terms, if $f_{pid}(entry)$ is the value of property ID \c pid of the entry \c entry,
   * then this function returns the \a range (=set of all reached values) of $f_{pid}$.
   *
   * KLFLibResourceSimpleEngine::queryValuesImpl() offers a very simple non-optimized implementation
   * of this function that you can use in your resource engine subclass if you don't want to do this
   * yourself. That function is automatically re-implemented if you subclass KLFLibResourceSimpleEngine.
   */
  virtual QList<QVariant> queryValues(const QString& subResource, int entryPropId) = 0;


  //! Returns all IDs in this resource (and this sub-resource)
  /** Returns a list of the ID of each entry in this resource.
   *
   * If sub-resources are supported, then returns only IDs in the given \c subResource.
   * Otherwise, the \c subResource parameter should be ignored.
   */
  virtual QList<KLFLib::entryId> allIds(const QString& subResource) = 0;

  //! Returns all IDs in this resource (and the default sub-resource)
  /** Returns a list of the ID of each entry in this resource.
   *
   * If sub-resources are supported, then returns only IDs in the default sub-resource
   * given by \ref defaultSubResource().
   *
   * The base implementation calls \ref allIds(const QString&) with the default sub-resource
   * as parameter. Subclasses need not reimplement this function, but rather
   * \ref allIds(const QString&) instead.
   */
  virtual QList<KLFLib::entryId> allIds();

  //! query all entries in this resource
  /** Returns all the entries in this library resource (in sub-resource \c subResource if
   * \ref FeatureSubResources is supported) with their corresponding IDs.
   *
   * \note Subclasses must reimplement this function to behave as described here.
   */
  virtual QList<KLFLibEntryWithId> allEntries(const QString& subResource,
					      const QList<int>& wantedEntryProperties = QList<int>()) = 0;

  //! query all entries in this resource
  /** Returns all the entries in this library resource (in default sub-resource if
   * \ref FeatureSubResources is supported) with their corresponding IDs.
   *
   * The default implementation calls
   * \ref allEntries(const QString& subResource, const QList<int>&) with the default subresource
   * as argument. See \ref setDefaultSubResource().
   */
  virtual QList<KLFLibEntryWithId> allEntries(const QList<int>& wantedEntryProperties = QList<int>());


  //! Specifies that the next operation (only) should not report progress
  void blockProgressReportingForNextOperation();

  //! (Un)Blocks generally progress reporting
  void blockProgressReporting(bool block);
  
signals:
  //! Emitted when data has changed
  /** This signal is emitted whenever data changes in the model (eg. due to an \ref insertEntries()
   * function call).
   *
   * The parameter \c subResource is the sub-resource in which the change was observed.
   *
   * The parameter \c modificationType is the type of modification that occured. It is one
   * of \ref InsertData, \ref ChangeData, \ref DeleteData, or \ref UnknownModification. (In
   * particular, sub-classes should not emit other modification types). The \c int type is
   * used for compatibility in Qt's SIGNAL-SLOT mechanism.
   *
   * An \c UnknownModification change means either the library resource changed completely,
   * or simply the backend does not wish to privide any information on which entries changed.
   * In any case, the receiver should consider all previously read data from the resource as
   * out of date and refresh all.
   *
   * The entries that were changed are given in the argument \c entryIdList.
   */
  void dataChanged(const QString& subResource, int modificationType,
		   const QList<KLFLib::entryId>& entryIdList);

  //! Emitted when the default sub-resource changes.
  void defaultSubResourceChanged(const QString& newDefaultSubResource);
  
  //! Emitted when a resource property changes.
  /** \param propId the ID of the property that changed. */
  void resourcePropertyChanged(int propId);
  
  //! Emitted when a sub-resource property changes.
  /** This signal should only be emitted by engines supporting feature \ref FeatureSubResourceProps
   * as well as \ref FeatureSubResources.
   *
   * \param subResource the affected sub-resource name
   * \param propId the ID of the property that changed
   */
  void subResourcePropertyChanged(const QString& subResource, int propId);

  //! Emitted when a sub-resource is created
  /** This signal should be emitted by engines supporting feature \ref FeatureSubResources, at
   * the end of a (successful) \ref createSubResource() call.\
   */
  void subResourceCreated(const QString& newSubResource);

  //! Emitted when a sub-resource is renamed
  /** This signal should be emitted by engines supporting feature \ref FeatureSubResources, at
   * the end of a (successful) \ref renameSubResource() call.\
   */
  void subResourceRenamed(const QString& oldSubResourceName,
			  const QString& newSubResourceName);

  //! Emitted when a sub-resource is deleted
  /** This signal should be emitted by engines supporting feature \ref FeatureSubResources, at
   * the end of a (successful) \ref deleteSubResource() call.
   */
  void subResourceDeleted(const QString& subResource);


  /** Emitted at the beginning of a long operation during which progress will be reported
   * by emission of KLFProgressReporter::progress() of the given object \c progressReporter.
   *
   * \param progressReporter is the object that will emit its progress() at regular intervals
   *   to inform caller of operation progress.
   * \param descriptiveText is some text describing the nature of the operation in progress
   *
   * Subclasses have to use KLFProgressReporter directly. It's very simple to use, example:
   * \code
   * int do_some_long_computations(...) {
   *   int num_of_steps = ... ;
   *   KLFProgressReporter progressReporter(0, num_of_steps, this);
   *   // ...
   *   int current_step = 0;
   *   for ( ... many iterations ... ) {
   *     progressReporter.doReportProgress(current_step++);
   *
   *     .... // perform a long computation iteration
   *
   *   }
   *   // finally emit the last progress value
   *   progressReporter.doReportProgress(num_of_steps);
   *   ...
   *   return some_result;
   * }
   * \endcode
   *
   * The signal operationStartReportingProgress() is suitable to use in conjunction with
   * a KLFProgressDialog.
   */
  void operationStartReportingProgress(KLFProgressReporter *progressReporter,
				       const QString& descriptiveText);



public slots:

  //! set a new resource title for this library resource
  /** Stores the new resource title. The title is a human string to display eg. in the
   * tabs of the KLFLibBrowser library browser. [KLFLibBrowser:  see klfapp library]
   *
   * This function calls directly \ref setResourceProperty().
   *
   * The default implementation should suffice; subclass \ref saveResourceProperty()
   * for actually saving the new value into the resource backend data, and for more control
   * over setting properties, or possibly subclass \ref setResourceProperty() for even more
   * control.
   *  */
  virtual bool setTitle(const QString& title);

  //! Set the resource to be locked
  /** See \ref locked() for more doc.
   *
   * If the feature flags do not contain \ref FeatureLocked, then this function returns
   * immediately FALSE. Otherwise, this function calls \ref setResourceProperty() with
   * arguments \ref PropLocked and the new value.
   *
   *
   * The default implementation should suffice; subclass \ref saveResourceProperty()
   * for actually saving the new value into the resource backend data, and for more control
   * over setting properties, or possibly subclass \ref setResourceProperty() for even more
   * control.
   */
  virtual bool setLocked(bool locked);

  /** Store the given view type in the ViewType property.
   *
   * Calls directly \ref setResourceProperty().
   *
   * The default implementation should suffice; subclass \ref saveResourceProperty()
   * for actually saving the new value into the resource backend data, and for more control
   * over setting properties, or possibly subclass \ref setResourceProperty() for even more
   * control.
   * */
  virtual bool setViewType(const QString& viewType);

  //! Set the resource to be read-only or not
  /** If the \ref FeatureReadOnly was given to the constructor, The base implementation sets
   * the read-only flag to \c readonly (this is then returned by \ref isReadOnly()). The
   * base implementation does nothing and returns FALSE if the feature \ref FeatureReadOnly is
   * not supported.
   */
  virtual bool setReadOnly(bool readonly);

  //! Set the default sub-resource
  /** When calling the variants of insertEntry(), changeEntry(), etc. that do not take a
   * sub-resource argument, and when this resource implements \ref FeatureSubResources, then
   * calls to those functions will access the <i>default sub-resource</i>, which can be
   * set with this function. 
   *
   * This function should be used only with subclasses implementing \ref FeatureSubResources.
   *
   * The default implementation remembers \c subResource to be the new \ref defaultSubResource() and
   * emits \ref defaultSubResourceChanged(). It does nothing if \c subResource is already the default
   * sub-resource.
   *
   * \warning Reimplementing this function has a drawback: it will not be called with the argument
   * given in the constructor (impossible to call reimplemented virtual methods in base constructor).
   * Instead, the sub-class has to explicitely call its own implementation in its own constructor
   * to ensure full proper initialization.
   */
  virtual void setDefaultSubResource(const QString& subResource);

  //! Create a new sub-resource
  /** If they implement the feature \ref FeatureSubResources, subclasses may reimplement this
   * function to create a new sub-resource named \c subResource, with human title \c subResourceTitle.
   *
   * \c subResourceTitle should be ignored for resources not implementing the \ref FeatureSubResourceProps
   * feature.
   *
   * \returns TRUE for success or FALSE for failure.
   *
   * Subclasses should reimplement this function to provide functionality if they wish. The default
   * implementation does nothing and returns FALSE.
   *
   * \note engines not implementing sub-resource properties should also subclass this function and
   *   not the other one, without the \c subResourceTitle parameter. This is because internally this
   *   function is ultimately called in all cases.
   */
  virtual bool createSubResource(const QString& subResource, const QString& subResourceTitle);

  //! Create a new sub-resource
  /** This function is provided for convenience. It calls
   * \code
   *  createSubResource(subResource, QString());
   * \endcode
   * and returns the same result.
   *
   * In other words, call this function if you don't want to provide a resource title, but subclasses
   * should re-implement the _other_ function to make sure full functionality is achieved (in particular
   * also engines not implementing sub-resource properties, which will then simply ignore the title
   * argument). This is because internally the other function is ultimately called in all cases.
   *
   * Again, the default implementation of this function sould be largely sufficient in most cases
   * and thus in principle needs not be reimplemented.
   */
  virtual bool createSubResource(const QString& subResource);

  /** Rename the sub-resource \c oldSubResourceName to \c newSubResourceName.
   *
   * \note we are talking about the resource <i>name</i> (eg. the table name in the database),
   *   not the <i>title</i> (stored as a sub-resource property, for engines supporting
   *   \ref FeatureSubResourceProps).
   *
   * Returns TRUE for success and FALSE for failure.
   *
   * Subclasses may reimplement this function to provide functionality. The default implementation
   * does nothing and returns FALSE.
   *
   * Subclasses should not forget to emit \ref subResourceRenamed() after a successful sub-resource
   * rename.
   *
   * \note Subclasses should also adjust the current defaultSubResource() if that is the one that
   *   was precisely renamed. Use a call to \ref setDefaultSubResource().
   */
  virtual bool renameSubResource(const QString& oldSubResourceName, const QString& newSubResourceName);

  /** Delete the given sub-resource
   *
   * Returns TRUE for success and FALSE for failure.
   *
   * Subclasses may reimplement this function to provide functionality. The default implementation
   * does nothing and returns FALSE.
   *
   * Subclasses should not forget to emit \ref subResourceDeleted() after the sub-resource
   * has been deleted (ie. upon a successful execution).
   *
   * \note Subclasses should also change the current defaultSubResource() if that is the one that
   *   was precisely deleted. Use a call to \ref setDefaultSubResource().
   */
  virtual bool deleteSubResource(const QString& subResource);


  /** Sets the given sub-resource property of sub-resource \c subResource to the value \c value,
   * if the operation is possible and legal.
   *
   * \returns TRUE for success, FALSE for failure.
   *
   * The default implementation does nothing and returns FALSE.
   */
  virtual bool setSubResourceProperty(const QString& subResource, int propId, const QVariant& value);


  //! Insert an entry into this resource
  /** This function is provided for convenience. Inserts the entry \c entry into the
   * subresource \c subResource of this resource. Resources not implementing the sub-resources
   * feature (\ref FeatureSubResources) should ignore the subResource parameter.
   *
   * API users should use the version of \ref insertEntry(const KLFLibEntry& entry) when dealing
   * with resources that do not implement the \ref FeatureSubResources feature.
   *
   * This function is already implemented as shortcut for calling the list version. Subclasses
   * need in principle NOT reimplement this function. */
  virtual entryId insertEntry(const QString& subResource, const KLFLibEntry& entry);

  //! Insert an entry into this resource
  /** This function is provided for convenience. Inserts the entry \c entry into this resource.
   *
   * Use this function for resources not supporting sub-resources (but subclasses still need
   * to reimplement the other function, ignoring the sub-resources argument), or use this
   * function when you explicitely want to use the default sub-resource.
   *
   * A reasonable default implementation is provided. Subclasses are not required to reimplement
   * this function.
   */
  virtual entryId insertEntry(const KLFLibEntry& entry);

  //! Insert new entries in this resource
  /** Inserts the given library entries (given as a \ref KLFLibEntry list) into this resource
   * and returns a list of the IDs that were attributed to the new entries (in the same
   * order as the given list). An individual ID of -1 means failure for that specific entry;
   * an empty list returned means a general failure, except if \c entrylist is empty.
   *
   * The entries are inserted into sub-resource \c subResource, if sub-resources are supported
   * (\ref FeatureSubResources). Otherwise the \c subResource parameter should be ignored
   * by subclasses.
   *
   * This function should be reimplemented by subclasses to actually save the new entries.
   * The reimplementation should make sure that the operation is permitted (eg. by checking
   * that \ref canModifyData() "canModifyData(InsertData)" is true, and should behave as
   * described above.
   *
   * Subclasses should then emit the \ref dataChanged() signal, and return a success/failure
   * code.
   */
  virtual QList<entryId> insertEntries(const QString& subResource, const KLFLibEntryList& entrylist) = 0;

  //! Insert new entries in this resource
  /** This function is provided for convenience. Inserts the entries \c entrylist into this resource.
   *
   * Use this function for resources not supporting sub-resources (but subclasses still need
   * to reimplement the other function, ignoring the sub-resources argument), or use this
   * function when you explicitely want to use the default sub-resource.
   *
   * A reasonable default implementation is provided. Subclasses are not required to reimplement
   * this function.
   */
  virtual QList<entryId> insertEntries(const KLFLibEntryList& entrylist);

  //! Change some entries in this resource.
  /** The entries specified by the ids \c idlist are modified. The properties given
   * in \c properties (which should be KLFLibEntry property IDs) are to be set to the respective
   * value in \c values for all the given entries in \c idlist. \c properties and \c values must
   * obviously be of same size.
   *
   * This function affects entries in sub-resource \c subResource for engines supporting feature
   * \ref FeatureSubResources.
   *
   * A return value of TRUE indicates general success and FALSE indicates a failure.
   *
   * This function should be reimplemented by subclasses to actually save the modified entries.
   * The reimplementation should make sure that the operation is permitted (eg. by checking
   * that \ref canModifyData() "canModifyData(ChangeData)" is true, and should behave as described
   * above.
   *
   * Subclasses should then emit the \ref dataChanged() signal, and return a success/failure
   * code.
   */
  virtual bool changeEntries(const QString& subResource, const QList<entryId>& idlist,
			     const QList<int>& properties, const QList<QVariant>& values) = 0;

  //! Change some entries in this resource
  /** This function is provided for convenience. The default implementation, which should largely
   * suffice in most cases, calls the other changeEntries() function, with the default sub-resource
   * \c defaultSubResource() as first argument.
   *
   * Use this function for resources not supporting sub-resources (but subclasses still need
   * to reimplement the other function, ignoring the sub-resources argument), or use this
   * function when you explicitely want to use the default sub-resource.
   */
  virtual bool changeEntries(const QList<entryId>& idlist, const QList<int>& properties,
			     const QList<QVariant>& values);

  //! Delete some entries in this resource.
  /** The entries specified by the ids \c idlist are deleted.
   *
   * A return value of TRUE indicates general success and FALSE indicates a failure.
   *
   * This function affects entries in sub-resource \c subResource for engines supporting feature
   * \ref FeatureSubResources.
   *
   * This function should be reimplemented by subclasses to actually delete the entries.
   * The reimplementation should make sure that the operation is permitted (eg. by checking
   * that \ref canModifyData() "canModifyData(DeleteData)" is true, and should behave as described
   * above.
   *
   * Subclasses should then emit the \ref dataChanged() signal, and return a success/failure
   * code.
   */
  virtual bool deleteEntries(const QString& subResource, const QList<entryId>& idlist) = 0;

  //! Delete some entries in this resource
  /** This function is provided for convenience. The default implementation, which should largely
   * suffice in most cases, calls the other deleteEntries() function, with the default sub-resource
   * \c defaultSubResource() as first argument.
   *
   * Use this function for resources not supporting sub-resources (but subclasses still need
   * to reimplement the other function, ignoring the sub-resources argument), or use this
   * function when you explicitely want to use the default sub-resource.
   */
  virtual bool deleteEntries(const QList<entryId>& idList);

  /** If the \ref FeatureSaveTo is supported (passed to the constructor), reimplement this
   * function to save the resource data in the new path specified by \c newPath.
   *
   * The \c newPath must be garanteed to have same schema as the previous url.
   *
   * \bug ........ THIS FUNCTION IS NOT COMPLETELY SUPPORTED IN KLFLibBrowser. ....... It also
   *   needs a "concept clarification", ie. what this is supposed to do exactly and how it is
   *   supposed to be used.
   */
  virtual bool saveTo(const QUrl& newPath);

  //! Set a resource property to the given value
  /** This function calls in turn:
   * - \ref canModifyProp() to check whether the property can be modified
   * - \ref saveResourceProperty() to check whether the operation is permitted (the value
   *   is acceptable, or any other check the subclass would want to perform) and to save
   *   the given value to the backend data;
   * - \ref KLFPropertizedObject::setProperty() to save the property locally;
   * - emits \ref resourcePropertyChanged() to notify other classes of the property change.
   *
   * \note This function fails immediately if \c propId is not a valid registered
   *   property ID, or if canModifyProp() returns FALSE.
   * */
  virtual bool setResourceProperty(int propId, const QVariant& value);

  //! Set the given property to the given value
  /** Very similar to calling \ref setResourceProperty() with the respective property
   * ID (see \ref KLFPropertizedObject::propertyIdForName()), except the property is
   * registered if it does't exist.
   *
   * The property is registered if it doesn't exist yet and the \ref canRegisterProperty()
   * returns TRUE.
   *
   * Once the property has been possibly registered, setResourceProperty() is called.
   */
  virtual bool loadResourceProperty(const QString& propName, const QVariant& value);


protected:

  //! Save a resource property to the backend resource data.
  /** Subclasses should reimplement this function to save the value of the given resource
   * property to the knew given value.
   *
   * If the new value is inacceptable, or if the operation is not permitted, the subclass
   * should return FALSE, in which case the resource property will not be changed.
   *
   */
  virtual bool saveResourceProperty(int propId, const QVariant& value) = 0;

  /** Whether it's possible to modify \a something (data, property value, etc.)
   */
  enum ModifyStatus {
    MS_CanModify = 0, //!< It's possible to modify that \a something
    MS_IsLocked = 1, //!< That \a something is resource-locked (ie., the only possible action is to unlock it)
    MS_SubResLocked = 2, //!< That \a something is sub-resource-locked
    MS_NotModifiable = 3 //!< That \a something is read-only or not modifiable for another reason
  };

  //! can modify data in resource (base common tests only)
  /** External classes: Don't call this function directly, use \ref canModifyData(), \ref canModifyProp(),
   * and \ref canModifySubResourceProperty() instead.
   *
   * Internal classes: this is useful for reimplementations of canModifyData(), canModifyProp(), etc.
   *
   * The latter and their reimplementations may call this function.
   *
   * This function can be reimplemented to take into account more factors (eg. a file being writable).
   *
   * \returns one value of the \ref ModifyStatus enum. See that documentation for more info.
   *
   * All supporting-feature checks are made correspondingly as needed. If nothing is supported
   * (read-only, locked, sub-resource properties) by default data is modifiable.
   */
  virtual ModifyStatus baseCanModifyStatus(bool inSubResource,
					   const QString& subResource = QString()) const;

  bool thisOperationProgressBlocked() const;

private:
  void initRegisteredProperties();

  QUrl pUrl;
  uint pFeatureFlags;
  bool pReadOnly;

  QString pDefaultSubResource;

  mutable bool pProgressBlocked;
  bool pThisOperationProgressBlockedOnly;

  KLF_DEBUG_DECLARE_REF_INSTANCE( QFileInfo(url().path()).fileName()+":"+defaultSubResource()  ) ;
};


Q_DECLARE_METATYPE(KLFLibResourceEngine::KLFLibEntryWithId)
  ;


KLF_EXPORT QDataStream& operator<<(QDataStream& stream,
				   const KLFLibResourceEngine::KLFLibEntryWithId& entrywid);
KLF_EXPORT QDataStream& operator>>(QDataStream& stream,
				   KLFLibResourceEngine::KLFLibEntryWithId& entrywid);


/** \brief Provides a simple API for reading library resources.
 *
 * This class provides default implementations of some pure virtual methods of
 * \ref KLFLibResourceEngine, which call other member functions. The goal is to make life
 * simpler to create a resource engine, where access speed is not a major concern.
 *
 * For example, KLFLibResourceEngine::allIds() is pure virtual. Normally it can be implemented
 * to be faster than allEntries(), depending on the engine backend. However the functionality
 * can as well easily be achieved by calling KLFLibResourceEngine::allEntries() and returning
 * just a list with all the IDs, at the price of losing optimization.
 *
 * This class provides non-optimized default implementations for allIds() (as given above),
 * hasEntry(), entries(), and query(), based on the data returned by allEntries() and
 * entry()
 *
 * Bear in mind that optimizing one or more of those functions is still possible, by
 * reimplementing them (!)
 */
class KLF_EXPORT KLFLibResourceSimpleEngine : public KLFLibResourceEngine
{
  Q_OBJECT
public:
  KLFLibResourceSimpleEngine(const QUrl& url, uint supportedfeatureflags, QObject *parent = NULL)
    : KLFLibResourceEngine(url, supportedfeatureflags, parent)
  {
  }
  virtual ~KLFLibResourceSimpleEngine() { }

  // these functions are implemented using the other base functions.

  virtual QList<KLFLib::entryId> allIds(const QString& subResource);
  virtual bool hasEntry(const QString&, entryId id);
  virtual QList<KLFLibEntryWithId> entries(const QString&, const QList<KLFLib::entryId>& idList,
					   const QList<int>& wantedEntryProperties = QList<int>());

  /** \brief Helper class to sort entries into a \ref KLFLibResourceEngine::QueryResult.
   */
  class QueryResultListSorter
  {
    KLFLibEntrySorter *mSorter;
    QueryResult *mResult;
    uint fillflags;
    bool reference_is_rawentrylist;
  public:
    /** Build an QueryResultListSorter object, that should sort entries according to
     * \c sorter. See also \ref KLFLibEntrySorter.
     *
     * \c sorter must not be NULL.
     */
    QueryResultListSorter(KLFLibEntrySorter *sorter, QueryResult *result);

    /*    QueryResultListSorter(const QueryResultListSorter& other); */

    /** \brief Compares \ref KLFLibEntry'ies */
    inline bool operator()(const KLFLibEntry& a, const KLFLibEntry& b)
    { return mSorter->operator()(a, b); }

    /** \brief Compares \ref KLFLibResourceEngine::KLFLibEntryWithId's */
    inline bool operator()(const KLFLibEntryWithId& a, const KLFLibEntryWithId& b)
    { return mSorter->operator()(a.entry, b.entry); }

    /** Returns the number of entries there are in the lists (ignoring those lists left empty, of
     * course). */
    int numberOfEntries();

    /** Inserts the entry-with-id \c entrywid, into the appropriate lists in the \c result that
     * was given to the constructor, such that the lists are ordered according to the sorter set
     * in the constructor.
     *
     * By \a appropriate we mean the lists for which the fill flags are set in the QueryResult object.
     *
     * If the set sorter's sorting property ID is \c -1, then the elements are simply
     * appended to the appropriate lists; sorting is disabled in this case.
     *
     * When sorting is enabled, this function assumes that the lists in \c result are sorted
     * appropriately. This is naturally the case if you only use this function to build the lists.
     * In other terms, don't call this function if you already added non-sorted items into the
     * list(s).
     *
     * \note if the fill flags include neither the raw entry list, nor the entry-with-id list,
     *   then the raw entry list is also filled, as it is not possible to just compare bare entry
     *   IDs (!)
     */
    void insertIntoOrderedResult(const KLFLibEntryWithId& entry);
  };

  virtual int query(const QString& subResource, const Query& query, QueryResult *result);

  virtual QList<QVariant> queryValues(const QString& subResource, int entryPropId);


  /** A basic implementation of query() based on matching the results of
   * <tt>resource->allEntries()</tt>. */
  static int queryImpl(KLFLibResourceEngine *resource, const QString& subResource,
		       const Query& query, QueryResult *result);

  /** A basic implementation of queryValues() based on looking at the results of
   * <tt>resource->allEntries()</tt> */
  static QList<QVariant> queryValuesImpl(KLFLibResourceEngine *resource, const QString& subResource,
					 int entryPropId);


  /** A simple entry condition tester. */
  static bool testEntryMatchConditionImpl(const KLFLib::EntryMatchCondition& condition,
					  const KLFLibEntry& libentry);
};



/** An abstract factory class for opening resources identified by their URL, and creating
 * objects of the currect subclass of KLFLibResourceEngine.
 *
 * See also \ref KLFLibResourceEngine, \ref KLFLibDBEngine, \ref KLFLibLegacyEngine.
 * More about factory common functions in \ref KLFFactoryManager documentation.
 */
class KLF_EXPORT KLFLibEngineFactory : public QObject, public KLFFactoryBase
{
  Q_OBJECT
public:
  /** A generalized way of passing arbitrary parameters for creating
   * new resources or saving resources to new locations.
   *
   */
  typedef QMap<QString,QVariant> Parameters;

  enum SchemeFunctions {
    FuncOpen   = 0x01, //!< Open Resources
    FuncCreate = 0x02, //!< Create New Resources
    FuncSaveTo = 0x04  //!< Save Resources to new locations
  };

  /** Constructs an engine factory and automatically regisers it. */
  KLFLibEngineFactory(QObject *parent = NULL);
  /** Destroys this engine factory and unregisters it. */
  virtual ~KLFLibEngineFactory();

  /** \brief A list of supported URL schemes this factory can open.
   *
   * If two factories provide a common scheme name, only the last instantiated is used;
   * the consequent ones will be ignored for that scheme name. See
   * \ref KLFFactoryBase::supportedTypes() and \ref KLFFactoryManager::findFactoryFor() */
  virtual QStringList supportedTypes() const = 0;

  /** \brief What this factory is capable of doing
   *
   * Informs the caller of what functionality this factory provides for the given \c scheme.
   *
   * The \c FuncOpen must be provided in every factory.
   *
   * \returns a bitwise-OR of flags defined in the \ref SchemeFunctions enum.
   *
   * The default implementation returns \c FuncOpen. */
  virtual uint schemeFunctions(const QString& scheme) const;

  /** Should return a human (short) description of the given scheme (which is one
   * returned by \ref supportedTypes()) */
  virtual QString schemeTitle(const QString& scheme) const = 0;

  /** Returns the widget type that should be used to present to user to "open" or "create" or
   * "save" a resource of the given \c scheme.
   *
   * For example, both \c "klf+sqlite" and \c "klf+legacy" schemes could return a "LocalFile"
   * widget that prompts to open/create/save-as a file. */
  virtual QString correspondingWidgetType(const QString& scheme) const = 0;

  /** Instantiate a library engine that opens resource stored at \c location. The resource
   * engine should be constructed as a child of object \c parent.
   */
  virtual KLFLibResourceEngine *openResource(const QUrl& location, QObject *parent = NULL) = 0;

  //! Create a new resource of given type and parameters
  /** Create the new resource, with the given settings. This function opens the resource and
   * returns the KLFLibResourceEngine object, which is instantiated as child of \c parent.
   *
   * The parameters' structure are defined for each widget type. That is, if the
   * \ref correspondingWidgetType() for a given scheme is eg. \c "LocalFile", then the
   * parameters are defined by whatever the \c "LocalFile" widget sets. For example
   * \c "LocalFile" documents its parameters in
   * \ref KLFLibBasicWidgetFactory::retrieveCreateParametersFromWidget(), eg. parameter
   * \c "Filename" contains a QString with the entered local file name.
   *
   * Additional parameters may also be set by KLFLibCreateResourceDlg itself (eg.
   * default sub-resource name/title, .........TODO............)
   *
   * The default implementation of this function does nothing and returns \c NULL. To enable
   * creating resources, reimplement \ref schemeFunctions() to return also \ref FuncCreate
   * and reimplement this function.
   */
  virtual KLFLibResourceEngine *createResource(const QString& scheme, const Parameters& parameters,
					       QObject *parent = NULL);

  //! Save the given resource to a new location
  /** Save the resource \c resource to the new location given by \c newLocation.
   *
   * The caller should garantee that \c resource is a resource engine of a scheme supported by
   * this factory.
   *
   * \note The resource a the new location is not opened. \c resource will still continue pointing
   *   to the previous location.
   *
   * For example, an \c "klf+sqlite" Sqlite database may choose to simply copy the database file
   * to the new location. This example is implemented in \ref KLFLibDBEngine::saveTo().
   *
   * \returns TRUE for success or FALSE for failure.
   *
   * The default implementation of this function does nothing and returns false. To enable
   * creating resources, reimplement \ref schemeFunctions() to return also \ref FuncCreate
   * and reimplement this function.
   */
  virtual bool saveResourceTo(KLFLibResourceEngine *resource, const QUrl& newLocation);




  /** Finds the last registered factory that should be able to open URL \c url (determined by
   * the URL's scheme) and returns a pointer to that factory.
   *
   * This function is provided for convenience; it is equivalent to
   * \code findFactoryFor(url.scheme()) \endcode
   */
  static KLFLibEngineFactory *findFactoryFor(const QUrl& url);

  /** Finds the last registered factory that should be able to open URLs with scheme \c urlScheme
   * and returns a pointer to that factory. */
  static KLFLibEngineFactory *findFactoryFor(const QString& urlScheme);

  /** Returns a concatenated list of all schemes that all registered factories support */
  static QStringList allSupportedSchemes();

  /** Finds the good factory for URL \c location, and opens the resource using that factory.
   * The created resource will be a child of \c parent. */
  static KLFLibResourceEngine *openURL(const QUrl& location, QObject *parent = NULL);

  /** Opens resource designated by \c url, and then lists the subresources. An empty list
   * is returned if the resource cannot be opened, or if the resource does not support
   * sub-resources.
   *
   * The resource is immedately closed after reading the list of sub-resources.
   *
   * This function:
   * - Finds the relevant factory with \ref findFactoryFor()
   * - Opens the resource with \ref openResource() using that factory
   * - fails if the resource does not support \ref KLFLibResourceEngine::FeatureSubResources
   * - lists the sub-resources
   * - closes the resource
   */
  static QStringList listSubResources(const QUrl& url);

  /** Opens resource designated by \c url, and then lists the subresources with as key
   * the resource name and as value the sub-resource title (if sub-resource properties
   * are supported, or an empty string if not). An empty map is returned if the resource
   * cannot be opened, or if the resource does not support sub-resources.
   *
   * This function works in a very similar way to \ref listSubResources().
   *
   * The resource is immedately closed after reading the list of sub-resources.
   */
  static QMap<QString,QString> listSubResourcesWithTitles(const QUrl& url);

private:
  static KLFFactoryManager pFactoryManager;
};



// -------------------------


class QMimeData;

//! Helper class to encode an entry list as mime data (abstract interface)
class KLF_EXPORT KLFAbstractLibEntryMimeEncoder
{
public:
  KLFAbstractLibEntryMimeEncoder();
  virtual ~KLFAbstractLibEntryMimeEncoder();

  //! A list of mime types this class can encode
  virtual QStringList supportedEncodingMimeTypes() const = 0;
  //! A list of mime types this class can decode
  virtual QStringList supportedDecodingMimeTypes() const = 0;

  virtual QByteArray encodeMime(const KLFLibEntryList& entryList, const QVariantMap& metaData,
				const QString& mimeType) const = 0;

  virtual bool decodeMime(const QByteArray& data, const QString& mimeType,
			  KLFLibEntryList *entryList, QVariantMap *metaData) const = 0;


  static QStringList allEncodingMimeTypes();
  static QStringList allDecodingMimeTypes();
  //! Creates a QMetaData with all known registered encoding mime types
  static QMimeData *createMimeData(const KLFLibEntryList& entryList, const QVariantMap& metaData);
  static bool canDecodeMimeData(const QMimeData *mimeData);
  static bool decodeMimeData(const QMimeData *mimeData, KLFLibEntryList *entryList,
			     QVariantMap *metaData);

  static KLFAbstractLibEntryMimeEncoder *findEncoderFor(const QString& mimeType,
							bool warnIfNotFound = true);
  static KLFAbstractLibEntryMimeEncoder *findDecoderFor(const QString& mimeType,
							bool warnIfNotFound = true);
  static QList<KLFAbstractLibEntryMimeEncoder*> encoderList();
private:

  static void registerEncoder(KLFAbstractLibEntryMimeEncoder *encoder);

  static QList<KLFAbstractLibEntryMimeEncoder*> staticEncoderList;
};





#ifdef KLF_DEBUG
#include <QDebug>
KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLib::StringMatch& smatch);
KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLib::PropertyMatch& pmatch);
KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLib::EntryMatchCondition& c);
KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibResourceEngine::Query& q);
KLF_EXPORT QDebug& operator<<(QDebug& dbg, const KLFLibResourceEngine::KLFLibEntryWithId& ewid);
#endif




#endif