1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #include "opendocumentsfilter.h"
27 
28 #include <coreplugin/editormanager/editormanager.h>
29 #include <coreplugin/editormanager/ieditor.h>
30 #include <coreplugin/locator/basefilefilter.h>
31 #include <utils/fileutils.h>
32 #include <utils/link.h>
33 #include <utils/linecolumn.h>
34 
35 #include <QAbstractItemModel>
36 #include <QFileInfo>
37 #include <QMutexLocker>
38 #include <QRegularExpression>
39 
40 using namespace Core;
41 using namespace Core::Internal;
42 using namespace Utils;
43 
OpenDocumentsFilter()44 OpenDocumentsFilter::OpenDocumentsFilter()
45 {
46     setId("Open documents");
47     setDisplayName(tr("Open Documents"));
48     setDefaultShortcutString("o");
49     setPriority(High);
50     setDefaultIncludedByDefault(true);
51 
52     connect(DocumentModel::model(), &QAbstractItemModel::dataChanged,
53             this, &OpenDocumentsFilter::refreshInternally);
54     connect(DocumentModel::model(), &QAbstractItemModel::rowsInserted,
55             this, &OpenDocumentsFilter::refreshInternally);
56     connect(DocumentModel::model(), &QAbstractItemModel::rowsRemoved,
57             this, &OpenDocumentsFilter::refreshInternally);
58 }
59 
matchesFor(QFutureInterface<LocatorFilterEntry> & future,const QString & entry)60 QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<LocatorFilterEntry> &future,
61                                                           const QString &entry)
62 {
63     QList<LocatorFilterEntry> goodEntries;
64     QList<LocatorFilterEntry> betterEntries;
65     QString postfix;
66     Link link = Link::fromString(entry, true, &postfix);
67 
68     const QRegularExpression regexp = createRegExp(link.targetFilePath.toString());
69     if (!regexp.isValid())
70         return goodEntries;
71 
72     const QList<Entry> editorEntries = editors();
73     for (const Entry &editorEntry : editorEntries) {
74         if (future.isCanceled())
75             break;
76         QString fileName = editorEntry.fileName.toString();
77         if (fileName.isEmpty())
78             continue;
79         QString displayName = editorEntry.displayName;
80         const QRegularExpressionMatch match = regexp.match(displayName);
81         if (match.hasMatch()) {
82             LocatorFilterEntry filterEntry(this, displayName, QString(fileName + postfix));
83             filterEntry.filePath = FilePath::fromString(fileName);
84             filterEntry.extraInfo = filterEntry.filePath.shortNativePath();
85             filterEntry.highlightInfo = highlightInfo(match);
86             if (match.capturedStart() == 0)
87                 betterEntries.append(filterEntry);
88             else
89                 goodEntries.append(filterEntry);
90         }
91     }
92     betterEntries.append(goodEntries);
93     return betterEntries;
94 }
95 
refreshInternally()96 void OpenDocumentsFilter::refreshInternally()
97 {
98     QMutexLocker lock(&m_mutex);
99     m_editors.clear();
100     const QList<DocumentModel::Entry *> documentEntries = DocumentModel::entries();
101     for (DocumentModel::Entry *e : documentEntries) {
102         Entry entry;
103         // create copy with only the information relevant to use
104         // to avoid model deleting entries behind our back
105         entry.displayName = e->displayName();
106         entry.fileName = e->fileName();
107         m_editors.append(entry);
108     }
109 }
110 
editors() const111 QList<OpenDocumentsFilter::Entry> OpenDocumentsFilter::editors() const
112 {
113     QMutexLocker lock(&m_mutex);
114     return m_editors;
115 }
116 
refresh(QFutureInterface<void> & future)117 void OpenDocumentsFilter::refresh(QFutureInterface<void> &future)
118 {
119     Q_UNUSED(future)
120     QMetaObject::invokeMethod(this, &OpenDocumentsFilter::refreshInternally, Qt::QueuedConnection);
121 }
122 
accept(LocatorFilterEntry selection,QString * newText,int * selectionStart,int * selectionLength) const123 void OpenDocumentsFilter::accept(LocatorFilterEntry selection,
124                                  QString *newText, int *selectionStart, int *selectionLength) const
125 {
126     Q_UNUSED(newText)
127     Q_UNUSED(selectionStart)
128     Q_UNUSED(selectionLength)
129     BaseFileFilter::openEditorAt(selection);
130 }
131