1 /*
2     SPDX-FileCopyrightText: 2008 Andreas Pakulat <apaku@gmx.de>
3 
4     SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "session.h"
8 
9 #include <QDir>
10 #include <QUrl>
11 
12 #include <KConfigGroup>
13 
14 #include <interfaces/iplugincontroller.h>
15 #include <interfaces/iplugin.h>
16 #include "core.h"
17 #include "sessioncontroller.h"
18 #include <interfaces/iprojectcontroller.h>
19 #include <interfaces/iproject.h>
20 #include <serialization/itemrepository.h>
21 
22 namespace KDevelop
23 {
24 
25 const QString Session::cfgSessionNameEntry = QStringLiteral("SessionName");
26 const QString Session::cfgSessionDescriptionEntry = QStringLiteral("SessionPrettyContents");
27 const QString Session::cfgSessionProjectsEntry = QStringLiteral("Open Projects");
28 const QString Session::cfgSessionOptionsGroup = QStringLiteral("General Options");
29 
30 class SessionPrivate
31 {
32 public:
33     SessionInfo info;
34     Session* const q;
35     bool isTemporary;
36 
pluginArea(const IPlugin * plugin)37     QUrl pluginArea( const IPlugin* plugin )
38     {
39         QString name = Core::self()->pluginController()->pluginInfo(plugin).pluginId();
40         QUrl url = QUrl::fromLocalFile(info.path + QLatin1Char('/') + name );
41         if( !QFile::exists( url.toLocalFile() ) ) {
42             QDir( info.path ).mkdir( name );
43         }
44         return url;
45     }
46 
SessionPrivate(Session * session,const QString & id)47     SessionPrivate( Session* session, const QString& id )
48         : info( Session::parse( id, true ) )
49         , q( session )
50         , isTemporary( false )
51     {
52     }
53 
updateDescription()54     void updateDescription()
55     {
56         buildDescription( info );
57         emit q->sessionUpdated( q );
58     }
59 
60     static QString generatePrettyContents( const SessionInfo& info );
61     static QString generateDescription( const SessionInfo& info );
62     static void buildDescription( SessionInfo& info );
63 };
64 
Session(const QString & id,QObject * parent)65 Session::Session( const QString& id, QObject* parent )
66         : ISession(parent)
67         , d_ptr(new SessionPrivate(this, id))
68 {
69 }
70 
71 Session::~Session() = default;
72 
name() const73 QString Session::name() const
74 {
75     Q_D(const Session);
76 
77     return d->info.name;
78 }
79 
containedProjects() const80 QList<QUrl> Session::containedProjects() const
81 {
82     Q_D(const Session);
83 
84     return d->info.projects;
85 }
86 
description() const87 QString Session::description() const
88 {
89     Q_D(const Session);
90 
91     return d->info.description;
92 }
93 
pluginDataArea(const IPlugin * p)94 QUrl Session::pluginDataArea( const IPlugin* p )
95 {
96     Q_D(Session);
97 
98     return d->pluginArea( p );
99 }
100 
config()101 KSharedConfigPtr Session::config()
102 {
103     Q_D(Session);
104 
105     return d->info.config;
106 }
107 
id() const108 QUuid Session::id() const
109 {
110     Q_D(const Session);
111 
112     return d->info.uuid;
113 }
114 
setName(const QString & newname)115 void Session::setName( const QString& newname )
116 {
117     Q_D(Session);
118 
119     d->info.name = newname;
120     d->info.config->group( QString() ).writeEntry( cfgSessionNameEntry, newname );
121     d->updateDescription();
122 }
123 
setContainedProjects(const QList<QUrl> & projects)124 void Session::setContainedProjects( const QList<QUrl>& projects )
125 {
126     Q_D(Session);
127 
128     d->info.projects = projects;
129     d->info.config->group( cfgSessionOptionsGroup ).writeEntry( cfgSessionProjectsEntry, projects );
130     d->updateDescription();
131 }
132 
setTemporary(bool temp)133 void Session::setTemporary(bool temp)
134 {
135     Q_D(Session);
136 
137     d->isTemporary = temp;
138 }
139 
isTemporary() const140 bool Session::isTemporary() const
141 {
142     Q_D(const Session);
143 
144     return d->isTemporary;
145 }
146 
path() const147 QString Session::path() const
148 {
149     Q_D(const Session);
150 
151     return d->info.path;
152 }
153 
generatePrettyContents(const SessionInfo & info)154 QString SessionPrivate::generatePrettyContents( const SessionInfo& info )
155 {
156     if( info.projects.isEmpty() )
157         return QString();
158 
159     QStringList projectNames;
160     projectNames.reserve( info.projects.size() );
161 
162     for (const QUrl& url : info.projects) {
163         IProject* project = nullptr;
164         if( ICore::self() && ICore::self()->projectController() ) {
165             project = ICore::self()->projectController()->findProjectForUrl( url );
166         }
167 
168         if( project ) {
169             projectNames << project->name();
170         } else {
171             QString projectName = url.fileName();
172             projectName.remove(QRegExp(QStringLiteral("\\.kdev4$"), Qt::CaseInsensitive));
173             projectNames << projectName;
174         }
175     }
176 
177     if( projectNames.isEmpty() ) {
178         return i18n("(no projects)");
179     } else {
180         return projectNames.join(QLatin1String(", "));
181     }
182 }
183 
generateDescription(const SessionInfo & info)184 QString SessionPrivate::generateDescription( const SessionInfo& info )
185 {
186     QString prettyContentsFormatted = generatePrettyContents( info );
187     QString description;
188 
189     if( info.name.isEmpty() ) {
190         description = prettyContentsFormatted;
191     } else {
192         description = info.name + QLatin1String(":  ") + prettyContentsFormatted;
193     }
194 
195     return description;
196 }
197 
buildDescription(SessionInfo & info)198 void SessionPrivate::buildDescription( SessionInfo& info )
199 {
200     QString description = generateDescription( info );
201 
202     info.description = description;
203     info.config->group( QString() ).writeEntry( Session::cfgSessionDescriptionEntry, description );
204     info.config->sync();
205 }
206 
parse(const QString & id,bool mkdir)207 SessionInfo Session::parse( const QString& id, bool mkdir )
208 {
209     SessionInfo ret;
210     QString sessionPath = SessionController::sessionDirectory(id);
211 
212     QDir sessionDir( sessionPath );
213     if( !sessionDir.exists() ) {
214         if( mkdir ) {
215             sessionDir.mkpath(sessionPath);
216             Q_ASSERT( sessionDir.exists() );
217         } else {
218             return ret;
219         }
220     }
221 
222     ret.uuid = id;
223     ret.path = sessionPath;
224     ret.config = KSharedConfig::openConfig(sessionPath + QLatin1String("/sessionrc"));
225 
226     KConfigGroup cfgRootGroup = ret.config->group( QString() );
227     KConfigGroup cfgOptionsGroup = ret.config->group( cfgSessionOptionsGroup );
228 
229     ret.name = cfgRootGroup.readEntry( cfgSessionNameEntry, QString() );
230     ret.projects = cfgOptionsGroup.readEntry( cfgSessionProjectsEntry, QList<QUrl>() );
231     SessionPrivate::buildDescription( ret );
232 
233     return ret;
234 }
235 
236 }
237 
238