1 /*
2  * SPDX-FileCopyrightText: 2009 Peter Penz <peter.penz19@gmail.com>
3  *
4  * SPDX-License-Identifier: GPL-2.0-or-later
5  */
6 
7 #ifndef VERSIONCONTROLOBSERVER_H
8 #define VERSIONCONTROLOBSERVER_H
9 
10 #include "dolphin_export.h"
11 
12 #include "kversioncontrolplugin.h"
13 
14 #include <KFileItem>
15 
16 #include <QList>
17 #include <QObject>
18 #include <QString>
19 #include <QUrl>
20 
21 class KFileItemList;
22 class KFileItemModel;
23 class KItemRangeList;
24 class QAction;
25 class QTimer;
26 class UpdateItemStatesThread;
27 
28 class DolphinView;
29 
30 /**
31  * @brief Observes all version control plugins.
32  *
33  * The items of the directory-model get updated automatically if the currently
34  * shown directory is under version control.
35  *
36  * @see VersionControlPlugin
37  */
38 class DOLPHIN_EXPORT VersionControlObserver : public QObject
39 {
40     Q_OBJECT
41 
42 public:
43     explicit VersionControlObserver(QObject* parent = nullptr);
44     ~VersionControlObserver() override;
45 
46     void setModel(KFileItemModel* model);
47     KFileItemModel* model() const;
48     void setView(DolphinView* view);
49     DolphinView* view() const;
50 
51     QList<QAction*> actions(const KFileItemList& items) const;
52 
53 Q_SIGNALS:
54     /**
55      * Is emitted if an information message with the content \a msg
56      * should be shown.
57      */
58     void infoMessage(const QString& msg);
59 
60     /**
61      * Is emitted if an error message with the content \a msg
62      * should be shown.
63      */
64     void errorMessage(const QString& msg);
65 
66     /**
67      * Is emitted if an "operation completed" message with the content \a msg
68      * should be shown.
69      */
70     void operationCompletedMessage(const QString& msg);
71 
72 private Q_SLOTS:
73     /**
74      * Invokes verifyDirectory() with a small delay. If delayedDirectoryVerification()
75      * is invoked before the delay has been exceeded, the delay will be reset. This
76      * assures that a lot of short requests for directory verification only result
77      * in one (expensive) call.
78      */
79     void delayedDirectoryVerification();
80 
81     /**
82      * Invokes verifyDirectory() with a small delay. In opposite to
83      * delayedDirectoryVerification() it and assures that the verification of
84      * the directory is done silently without information messages.
85      */
86     void silentDirectoryVerification();
87 
88     /**
89      * Invokes delayedDirectoryVerification() only if the itemsChanged() signal has not
90      * been triggered by the VCS plugin itself.
91      */
92     void slotItemsChanged(const KItemRangeList& itemRanges, const QSet<QByteArray>& roles);
93 
94     void verifyDirectory();
95 
96     /**
97      * Is invoked if the thread m_updateItemStatesThread has been finished
98      * and applys the item states.
99      */
100     void slotThreadFinished();
101 
102 private:
103     typedef QPair<KFileItem, KVersionControlPlugin::ItemVersion> ItemState;
104 
105     void updateItemStates();
106 
107     /**
108      * It creates a item state list for every expanded directory and stores
109      * this list together with the directory url in the \a itemStates map.
110      *
111      * @itemStates      A map of item state lists for every expanded directory
112      *                  and its items, where the "key" is the directory url and
113      *                  the "value" is a list of ItemStates for every item
114      *                  within this directory.
115      * @firstIndex      The index to start the processing from, this is needed
116      *                  because this function is recursively called.
117      *
118      * @return          The number of (recursive) processed items.
119      */
120     int createItemStatesList(QMap<QString, QVector<ItemState> >& itemStates,
121                              const int firstIndex = 0);
122 
123     /**
124      * Returns a matching plugin for the given directory.
125      * 0 is returned, if no matching plugin has been found.
126      */
127     KVersionControlPlugin* searchPlugin(const QUrl& directory);
128 
129     /**
130      * Returns true, if the directory contains a version control information.
131      */
132     bool isVersionControlled() const;
133 
134 private:
135     void initPlugins();
136 
137     bool m_pendingItemStatesUpdate;
138     bool m_silentUpdate; // if true, no messages will be send during the update
139                          // of version states
140     QString m_localRepoRoot;
141 
142     DolphinView* m_view;
143     KFileItemModel* m_model;
144 
145     QTimer* m_dirVerificationTimer;
146 
147     bool m_pluginsInitialized;
148     KVersionControlPlugin* m_plugin;
149     QList<QPointer<KVersionControlPlugin>> m_plugins;
150     UpdateItemStatesThread* m_updateItemStatesThread;
151 
152     friend class UpdateItemStatesThread;
153 };
154 
155 #endif // REVISIONCONTROLOBSERVER_H
156 
157