"Fossies" - the Fresh Open Source Software Archive

Member "texstudio-2.12.22/src/symbolpanel/symbollistmodel.cpp" (15 Jan 2020, 7861 Bytes) of package /linux/misc/texstudio-2.12.22.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "symbollistmodel.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.12.20_vs_2.12.22.

    1 #include "symbollistmodel.h"
    2 #include "smallUsefulFunctions.h"
    3 #include "qsvgrenderer.h"
    4 
    5 /*!
    6  * A model for providing all the symbols. Specializations can be done using
    7  * QSortFilterProxyModels. This means that we have to maintain all the relevant
    8  * information (also usage count and favorites) within the model.
    9  *
   10  * This may be a bit heavy and inefficient but does the job so far. It reliefs
   11  * us from providing extra specialized models for "most used" and "favorites"
   12  * based on the same data.
   13  */
   14 
   15 SymbolListModel::SymbolListModel(QVariantMap usageCountMap, QStringList favoriteList) :
   16     iconSizeHint(32)
   17 {
   18     foreach (const QString &key, usageCountMap.keys()) {
   19         usageCount.insert(key, usageCountMap.value(key).toInt());
   20     }
   21     favoriteIds = favoriteList;
   22 }
   23 
   24 void SymbolListModel::load(QString category)
   25 {
   26     QStringList files;
   27     files = findResourceFiles("symbols-ng/" + category, "img*.*");
   28     if (files.isEmpty()) // fallback
   29         files = findResourceFiles("symbols/" + category, "img*.png");
   30 
   31     QStringList fullNames;
   32     foreach (const QString &partName, files)
   33         fullNames << category + "/" + partName;
   34     if (fullNames.length() == 0) {
   35         qDebug() << ("No symbols found for category: " + category);
   36     }
   37 
   38     loadSymbols(category, fullNames);
   39 }
   40 
   41 SymbolItem loadSymbolFromSvg(QString fileName)
   42 {
   43     QFile file(fileName);
   44 
   45     if (!file.open( QIODevice::ReadOnly)) {
   46         qDebug() << "could not open file";
   47         return SymbolItem();
   48     }
   49 
   50     QString errorMsg;
   51     int errorLine, errorColumn;
   52     QDomDocument doc("svg");
   53 
   54     if (!doc.setContent( &file, false, &errorMsg, &errorLine, &errorColumn) ) {
   55         qDebug() << "could not find xml content";
   56         qDebug() << errorMsg;
   57         qDebug() << "line is " << errorLine;
   58         qDebug() << "column is " << errorColumn;
   59         file.close();
   60         return SymbolItem();
   61     }
   62     file.close();
   63 
   64     // check root element
   65     QDomElement root = doc.documentElement();
   66     if ( root.tagName() != "svg" ) {
   67         qDebug() << "wrong format";
   68         return SymbolItem();
   69     }
   70 
   71     SymbolItem item;
   72 
   73     QDomNodeList nl = root.elementsByTagName("title");
   74     if (!nl.isEmpty()) {
   75         QDomNode n = nl.at(0);
   76         item.command = n.toElement().text();
   77     }
   78     nl = root.elementsByTagName("desc");
   79     if (!nl.isEmpty()) {
   80         QDomNode n = nl.at(0);
   81         item.packages = n.toElement().attribute("Packages");
   82     }
   83     nl = root.elementsByTagName("additionalInfo");
   84 
   85     if (!nl.isEmpty()) {
   86         QDomNode n = nl.at(0);
   87         item.unicode = n.toElement().attribute("CommandUnicode");
   88 
   89     }
   90 
   91     item.iconFile = fileName;
   92     item.icon = QIcon(fileName);
   93     return item;
   94 }
   95 
   96 void SymbolListModel::loadSymbols(const QString &category, const QStringList &fileNames)
   97 {
   98     for (int i = 0; i < fileNames.size(); ++i) {
   99         QString iconName = fileNames.at(i);
  100         QString fileName = findResourceFile("symbols-ng/" + iconName);
  101         if (fileName.isEmpty())
  102             fileName = findResourceFile("symbols/" + iconName);
  103 
  104         SymbolItem symbolItem;
  105 
  106         if (fileName.endsWith("svg")) {
  107             symbolItem = loadSymbolFromSvg(fileName);
  108         } else {
  109             QImage img = QImage(fileName);
  110             symbolItem.command = img.text("Command");
  111             symbolItem.packages = img.text("Packages");
  112             symbolItem.unicode = img.text("CommandUnicode");
  113             symbolItem.iconFile = fileName;
  114             symbolItem.icon = QIcon(fileName);
  115         }
  116         if (!symbolItem.unicode.isEmpty()) {
  117             // convert to real unicode
  118             QString helper;
  119             QStringList listOfChars = symbolItem.unicode.split(",");
  120             for (int i = 0; i < listOfChars.size(); i++) {
  121                 QString StrCode = listOfChars.value(i, "");
  122                 StrCode = StrCode.mid(2); // Remove U+
  123                 bool ok;
  124                 int code = StrCode.toInt(&ok);
  125                 if (ok)
  126                     helper += QChar(code);
  127             }
  128             symbolItem.unicode = helper;
  129 
  130         }
  131 
  132         symbolItem.category = category;
  133         symbolItem.id = category + '/' + symbolItem.command.mid(1);  // e.g. "greek/alpha"
  134 
  135         symbols.append(symbolItem);
  136     }
  137     return;
  138 }
  139 
  140 QVariantMap SymbolListModel::usageCountAsQVariantMap() const {
  141     QVariantMap map;
  142     foreach (const QString &key, usageCount.keys()) {
  143         map.insert(key, usageCount.value(key, 0));
  144     }
  145     return map;
  146 }
  147 
  148 QStringList SymbolListModel::favorites() const
  149 {
  150     return favoriteIds;
  151 }
  152 
  153 int SymbolListModel::rowCount(const QModelIndex &parent) const
  154 {
  155     Q_UNUSED(parent)
  156     return symbols.count();
  157 }
  158 
  159 QVariant SymbolListModel::data(const QModelIndex &index, int role) const
  160 {
  161     int r = index.row();
  162     if (r < 0 || r >= symbols.count())
  163         return QVariant();
  164 
  165     switch (role) {
  166     case Qt::DisplayRole:
  167         return QVariant();  // we do only want symbols, so we do not return a text
  168         //return symbols[r].command;
  169     case Qt::DecorationRole:
  170         return getIcon(symbols[r]);
  171     case Qt::ToolTipRole:
  172         return getTooltip(symbols[r]);
  173     case IdRole:
  174         return symbols[r].id;
  175     case CommandRole:
  176         return symbols[r].command;
  177     case UnicodeRole:
  178         return symbols[r].unicode;
  179     case CategoryRole:
  180         return symbols[r].category;
  181     case UsageCountRole:
  182         return usageCount.value(symbols[r].id, 0);
  183     case FavoriteRole:
  184         return QVariant(favoriteIds.contains(symbols[r].id));
  185     }
  186     return QVariant();
  187 }
  188 
  189 void SymbolListModel::incrementUsage(const QString &id)
  190 {
  191     usageCount.insert(id, usageCount.value(id, 0) + 1);
  192     for (int i=0; i<symbols.count(); i++) {
  193         if (symbols[i].id == id) {
  194 #if QT_VERSION > 0x050000
  195             emit dataChanged(index(i, 0), index(i, 0), (QVector<int>() << UsageCountRole));
  196 #else
  197             emit dataChanged(index(i, 0), index(i, 0));
  198 #endif
  199             break;
  200         }
  201     }
  202 }
  203 
  204 void SymbolListModel::addFavorite(const QString &id)
  205 {
  206     if (!favoriteIds.contains(id)) {
  207         favoriteIds.append(id);
  208         for (int i=0; i<symbols.count(); i++) {
  209             if (symbols[i].id == id) {
  210 #if QT_VERSION > 0x050000
  211                 emit dataChanged(index(i, 0), index(i, 0), (QVector<int>() << FavoriteRole));
  212 #else
  213                 emit dataChanged(index(i, 0), index(i, 0));
  214 #endif
  215                 emit favoritesChanged();
  216                 break;
  217             }
  218         }
  219     }
  220 }
  221 
  222 void SymbolListModel::removeFavorite(const QString &id)
  223 {
  224     if (favoriteIds.removeOne(id)) {
  225         for (int i=0; i<symbols.count(); i++) {
  226             if (symbols[i].id == id) {
  227 #if QT_VERSION > 0x050000
  228                 emit dataChanged(index(i, 0), index(i, 0), (QVector<int>() << FavoriteRole));
  229 #else
  230                 emit dataChanged(index(i, 0), index(i, 0));
  231 #endif
  232                 emit favoritesChanged();
  233                 break;
  234             }
  235         }
  236     }
  237 }
  238 
  239 QIcon SymbolListModel::getIcon(const SymbolItem &item) const
  240 {
  241 #if defined( Q_OS_MAC ) && (QT_VERSION >= 0x050500) && (QT_VERSION < QT_VERSION_CHECK(5,14,0))
  242     // work-around for another QT/OSX bug
  243     if(item.iconFile.endsWith(".svg")){
  244         const int sz = iconSizeHint + 4;
  245         QSvgRenderer svgRender(item.iconFile);
  246         QImage img(2*sz, 2*sz, QImage::Format_ARGB32);
  247         //img.setDevicePixelRatio(2.0);
  248         img.fill(0x000000000);
  249         QPainter p(&img);
  250         QSize svgSize=svgRender.defaultSize()*4;
  251         if(svgSize.width()>2*sz){
  252             svgSize.setWidth(2*sz);
  253             svgSize.setHeight(svgSize.height()*2*sz/svgSize.width());
  254         }
  255         svgRender.render(&p,QRectF(QPointF((2.0*sz-svgSize.width())/2,0),svgSize));
  256         return QIcon(QPixmap::fromImage(img));
  257     }else{
  258         return QIcon(item.iconFile);
  259     }
  260 #else
  261     //QIcon *icon = new QIcon(item.iconFile);
  262     //qDebug() << item.command << icon.actualSize(QSize(iconSizeHint, iconSizeHint));
  263     return item.icon;
  264 #endif
  265 }
  266 
  267 QString SymbolListModel::getTooltip(const SymbolItem &item) const
  268 {
  269     QStringList args, pkgs;
  270 
  271     QString label = item.command;
  272     label.replace("<", "&lt;");
  273     label = tr("Command: ") + "<b>" + label + "</b>";
  274 
  275     QRegExp rePkgs("(?:\\[(.*)\\])?\\{(.*)\\}");
  276 
  277     args.clear();
  278     pkgs.clear();
  279 
  280     if ( rePkgs.indexIn(item.packages) != -1 ) {
  281         args = rePkgs.cap(1).split(",");
  282         pkgs = rePkgs.cap(2).split(",");
  283     }
  284     if ( pkgs.count() > 0 ) {
  285         if (pkgs.count() == 1)
  286             label += "<br>" + tr("Package: ");
  287         else
  288             label += "<br>" + tr("Packages: ");
  289 
  290         for ( int j = 0; j < pkgs.count() ; j++ ) {
  291             if (j > 0) label += "\n";
  292             if ( j < args.count() && !args[j].isEmpty())
  293                 label = label + "[" + args[j] + "]" + pkgs[j];
  294             else
  295                 label = label + pkgs[j] ;
  296         }
  297     }
  298     if (!item.unicode.isEmpty())
  299         label += "<br>" + tr("Unicode Character: ") + item.unicode;
  300     return label;
  301 }
  302 
  303 
  304