Emphasize symlinks in QtCreator's projectexplorer



  • Hi there,

    I want to somehow highlight or mark symlinks in the projectexplorer.
    Is this possible via any configuration of QtCreator?

    If that is not possible, I want to add this functionality via a plugin. Can you give me any hints on where I have to look in the source code of QtCreator to find the part that is responsible for rendering the filenames in the project explorer?

    Thanks!

    Markus



  • Ok, found the correct place to introduce my changes.
    See diff against v2.1.0-rc1 below:

    @diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp
    index f17337c..cdfd5e8 100644
    --- a/src/plugins/projectexplorer/projectmodels.cpp
    +++ b/src/plugins/projectexplorer/projectmodels.cpp
    ATAT -224,6 +224,7 ATAT QVariant FlatModel::data(const QModelIndex &index, int role) const

     if (Node *node = nodeForIndex(index)) {
         FolderNode *folderNode = qobject_cast<FolderNode*>(node);
    
    •    QFileInfo fi(node->path());
         switch (role) {
         case Qt::DisplayRole:
         case Qt::EditRole: {
      

    ATAT -248,9 +249,18 ATAT QVariant FlatModel::data(const QModelIndex &index, int role) const
    QFont font;
    if (node == m_startupProject)
    font.setBold(true);

    •        if (fi.isSymLink()) {
      
    •            font.setItalic(true);
      
    •        }
             result = font;
             break;
         }
      
    •    case Qt::ForegroundRole: {
      
    •        if (fi.isSymLink()) {
      
    •            result = QBrush(Qt::blue);
      
    •            break;
      
    •        }
      
    •    }
         case ProjectExplorer::Project::FilePathRole: {
             result = node->path();
             break;@
      

    However, I am not sure right now whether this functionality can be added via a plugin...

    @the Trolls: do you think this is doable?

    Regards,
    Markus


  • Moderators

    I doubt that you can add this kind of stuff as a plugin without doing a new widget.

    You could of course submit this as a merge request an gitorious for us to put into Qt Creator:) The process to do so is outlined "here":http://qt.gitorious.org/qt/pages/QtContributionGuidelines. Most of it is a one-time thing, so it is not as scary as it looks on first glance:)

    PS: We need to go through gitorious for legal reasons, so unfortunately I can not just take your patch from here, sorry.

    [Changed smileys to unconfuse Textile]



  • Thanks for you answer.
    I am facing a problem with gitorious.org and our corporate network. I can only use the http clone urls. And up to now I am not able to push via http.. :(
    In addition to that it is not always possible to successfully clone the repo in one shot. From time to time the connection to gitorious breaks away and then I have to start over, because git clone over http is not resumable ... * sigh *

    Well I will see If I somehow manage to do the gitorious process and jump the initial hurdle =)


  • Moderators

    Company networks can be very painful at times, I have been behind some really annoying corporate firewalls myself!

    By the way: How badly does your change effect performance? This change does trigger two stat-calls per file, doesn't it?



  • Sounds like something that should be cached, if you ask me.



  • [quote author="Tobias Hunger" date="1295435080"]
    By the way: How badly does your change effect performance? This change does trigger two stat-calls per file, doesn't it?
    [/quote]
    Well I tried to trace that with strace:

    • opened QtCreator without a project
    • started strace and attached to the pid (piped the output of strace to trace.txt)
    • opened a project containing 1700 files with several entries being symlinks (one of them foo.cnf)
    • clicked on the + icon to expand the project tree
    • grep foo.cnf trace.txt | wc -l returned 5 before my changes
    • grep foo.cnf trace.txt | wc -l returned 17 after my changes

    I am quite surprised that it actually increases to 17, which means 12 more stat calls.. O_o

    So I quickly checked the results for a simple binary.
    The following has only 2 stat calls (one stat and one lstat):
    @QFileInfo fi("bar.txt");
    fi.isSymLink();@

    So I assume that my code gets called quite often because the ProjectModel::data() gets called a lot.

    From a users point I could not perceive that QtCreator was slowed down by my changes.


  • Moderators

    I am not surprised. The data() method is used rather often as that is the method providing access to the data of the model:-) So whenever you scroll something into view or whenever the view thinks something might have turned invalid it will need to call data(...) again. For this reason it makes sense to keep potentially expensive computations out of this method.



  • [quote author="Tobias Hunger" date="1295451032"]I am not surprised. The data() method is used rather often as that is the method providing access to the data of the model:-)
    [/quote]
    Yeah I know =)
    [quote author="Tobias Hunger" date="1295451032"] ... For this reason it makes sense to keep potentially expensive computations out of this method.[/quote]

    I tried another approach because of the above:
    I moved the QFileInfo Part into the ctor of ProjectExplorer::Node and stored the result of QFileInfo::isSymLink() into a new member of the node: bool ProjectExplorer::Node::m_isSymLink.
    Then I added a getter function bool ProjectExplorer::Node::isSymLink().

    These changes result into less stat calls, because QFileInfo::isSymLink gets only called upon construction of the Node and not each time the model is queried.

    What do you think about this approach?

    In addition to that I found out that there is a ToDo comment in projectmodels.cpp line 233:

    @result = QFileInfo(node->path()).fileName(); //TODO cache that?@

    So it seems to me that there is already someone thinking about how to cache the QFileInfo part.
    Do you have any hints on that?

    last but not least: the current diff:

    @
    diff --git a/src/plugins/projectexplorer/projectmodels.cpp b/src/plugins/projectexplorer/projectmodels.cpp
    index f17337c..b5b5379 100644
    --- a/src/plugins/projectexplorer/projectmodels.cpp
    +++ b/src/plugins/projectexplorer/projectmodels.cpp
    ATAT -248,9 +248,18 ATAT QVariant FlatModel::data(const QModelIndex &index, int role) const
    QFont font;
    if (node == m_startupProject)
    font.setBold(true);

    •        if (node->isSymLink()) {
      
    •            font.setItalic(true);
      
    •        }
             result = font;
             break;
         }
      
    •    case Qt::ForegroundRole: {
      
    •        if (node->isSymLink()) {
      
    •            result = QBrush(Qt::blue);
      
    •            break;
      
    •        }
      
    •    }
         case ProjectExplorer::Project::FilePathRole: {
             result = node->path();
             break;
      

    diff --git a/src/plugins/projectexplorer/projectnodes.cpp b/src/plugins/projectexplorer/projectnodes.cpp
    index 581c19b..60b398a 100644
    --- a/src/plugins/projectexplorer/projectnodes.cpp
    +++ b/src/plugins/projectexplorer/projectnodes.cpp
    ATAT -61,7 +61,8 ATAT Node::Node(NodeType nodeType,
    m_folderNode(0),
    m_path(filePath)
    {

    • QFileInfo fi(filePath);
    • m_isSymLink = fi.isSymLink();
      }

    NodeType Node::nodeType() const
    ATAT -113,6 +114,11 ATAT void Node::setPath(const QString &path)
    m_path = path;
    }

    +bool Node::isSymLink()
    +{

    • return m_isSymLink;
      +}

    /*!
    \class FileNode

    diff --git a/src/plugins/projectexplorer/projectnodes.h b/src/plugins/projectexplorer/projectnodes.h
    index 62a7f29..507ac54 100644
    --- a/src/plugins/projectexplorer/projectnodes.h
    +++ b/src/plugins/projectexplorer/projectnodes.h
    ATAT -92,6 +92,8 ATAT public:
    FolderNode *parentFolderNode() const; // parent folder or project
    QString path() const; // file system path

    • bool isSymLink();

    protected:
    Node(NodeType nodeType, const QString &path);

    ATAT -105,6 +107,8 ATAT private:
    ProjectNode *m_projectNode;
    FolderNode *m_folderNode;
    QString m_path;

    • bool m_isSymLink;
      };

    class PROJECTEXPLORER_EXPORT FileNode : public Node {
    @


  • Moderators

    Lines 9-11 could be collapsed to @font.setItalic(node->isSymlink());@

    I would further suggest moving the m_isSymLink member declaration up a bit: The NodeType enum might leave a hole in the struct that the bool might just fit into. That would save a couple of bytes of padding per Node.

    "kkoehne":http://gitorious.org/~kkoehne added the TODO item according to git blame. Just ask him directly:-)



  • [quote author="Tobias Hunger" date="1295521416"]Lines 9-11 could be collapsed to @font.setItalic(node->isSymlink());@
    [/quote]
    Even if you don't choose to collapse all that much (readability?), the braces still should be removed, according to the "coding style guidelines":http://qt.gitorious.org/qt/pages/QtCodingStyle.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.