1 /*
2  * LibrePCB - Professional EDA for everyone!
3  * Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
4  * https://librepcb.org/
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef LIBREPCB_WORKSPACE_H
21 #define LIBREPCB_WORKSPACE_H
22 
23 /*******************************************************************************
24  *  Includes
25  ******************************************************************************/
26 #include <librepcb/common/fileio/directorylock.h>
27 #include <librepcb/common/version.h>
28 
29 #include <QtCore>
30 
31 /*******************************************************************************
32  *  Namespace / Forward Declarations
33  ******************************************************************************/
34 namespace librepcb {
35 
36 namespace library {
37 class Library;
38 }
39 
40 namespace project {
41 class Project;
42 }
43 
44 namespace workspace {
45 
46 class ProjectTreeModel;
47 class RecentProjectsModel;
48 class FavoriteProjectsModel;
49 class WorkspaceSettings;
50 class WorkspaceLibraryDb;
51 
52 /*******************************************************************************
53  *  Class Workspace
54  ******************************************************************************/
55 
56 /**
57  * @brief The Workspace class represents a workspace with all its data (library,
58  * projects, settings, ...)
59  *
60  * To access the settings of the workspace, use the method #getSettings().
61  */
62 class Workspace final : public QObject {
63   Q_OBJECT
64 
65 public:
66   // Constructors / Destructor
67   Workspace() = delete;
68   Workspace(const Workspace& other) = delete;
69 
70   /**
71    * @brief Constructor to open an existing workspace
72    *
73    * @param wsPath        The filepath to the workspace directory
74    * @param lockCallback  A callback which gets called if the workspace
75    *                      directory is locked, to decide what to do in this
76    *                      case.
77    *
78    * @throw Exception If the workspace could not be opened, this constructor
79    * throws an exception.
80    */
81   explicit Workspace(const FilePath& wsPath,
82                      DirectoryLock::LockHandlerCallback lockCallback = nullptr);
83 
84   /**
85    * The destructor
86    */
87   ~Workspace() noexcept;
88 
89   // Getters
90 
91   /**
92    * @brief Get the filepath to the workspace directory
93    */
getPath()94   const FilePath& getPath() const { return mPath; }
95 
96   /**
97    * @brief Get the filepath to the "projects" directory in the workspace
98    */
getProjectsPath()99   const FilePath& getProjectsPath() const { return mProjectsPath; }
100 
101   /**
102    * @brief Get the filepath to the version directory (v#) in the workspace
103    */
getMetadataPath()104   const FilePath& getMetadataPath() const { return mMetadataPath; }
105 
106   /**
107    * @brief Get the filepath to the "v#/libraries" directory in the workspace
108    */
getLibrariesPath()109   const FilePath& getLibrariesPath() const { return mLibrariesPath; }
110 
111   /**
112    * @brief Get the filepath to the "v#/libraries/local" directory
113    */
getLocalLibrariesPath()114   FilePath getLocalLibrariesPath() const {
115     return mLibrariesPath.getPathTo("local");
116   }
117 
118   /**
119    * @brief Get the filepath to the "v#/libraries/remote" directory
120    */
getRemoteLibrariesPath()121   FilePath getRemoteLibrariesPath() const {
122     return mLibrariesPath.getPathTo("remote");
123   }
124 
125   ProjectTreeModel& getProjectTreeModel() const noexcept;
126   RecentProjectsModel& getRecentProjectsModel() const noexcept;
127   FavoriteProjectsModel& getFavoriteProjectsModel() const noexcept;
128 
129   /**
130    * @brief Get the workspace settings
131    */
getSettings()132   WorkspaceSettings& getSettings() const { return *mWorkspaceSettings; }
133 
134   // Library Management
135 
136   /**
137    * @brief Get the workspace library database
138    */
getLibraryDb()139   WorkspaceLibraryDb& getLibraryDb() const { return *mLibraryDb; }
140 
141   // Project Management
142 
143   /**
144    * @brief setLastRecentlyUsedProject
145    * @param filepath
146    */
147   void setLastRecentlyUsedProject(const FilePath& filepath) noexcept;
148 
149   /**
150    * @brief Check whether a project is in the favorite project list or not
151    *
152    * @param filepath  The filepath to a *.lpp project file
153    *
154    * @return True if the specified project is in the favorites list, false
155    * otherwise
156    */
157   bool isFavoriteProject(const FilePath& filepath) const noexcept;
158 
159   /**
160    * @brief Add a project to the favorite projects list
161    *
162    * @param filepath  The filepath to a *.lpp project file
163    */
164   void addFavoriteProject(const FilePath& filepath) noexcept;
165 
166   /**
167    * @brief Remove a project from the favorite projects list
168    *
169    * @param filepath  The filepath to a *.lpp project file
170    */
171   void removeFavoriteProject(const FilePath& filepath) noexcept;
172 
173   // Operator Overloadings
174   Workspace& operator=(const Workspace& rhs) = delete;
175 
176   // Static Methods
177 
178   /**
179    * @brief Check whether a filepath points to a valid workspace directory or
180    * not
181    *
182    * @param path  A path to a directory
183    *
184    * @return True if the path is a valid workspace directory, false otherwise
185    */
186   static bool isValidWorkspacePath(const FilePath& path) noexcept;
187 
188   /**
189    * @brief getFileFormatVersionsOfWorkspace
190    * @param path
191    * @return
192    */
193   static QList<Version> getFileFormatVersionsOfWorkspace(
194       const FilePath& path) noexcept;
195 
196   /**
197    * @brief getHighestFileFormatVersionOfWorkspace
198    * @param path
199    * @return
200    */
201   static tl::optional<Version> getHighestFileFormatVersionOfWorkspace(
202       const FilePath& path) noexcept;
203 
204   /**
205    * @brief Create a new workspace
206    *
207    * @param path  A path to a directory where to create the new workspace
208    *
209    * @throws Exception on error.
210    */
211   static void createNewWorkspace(const FilePath& path);
212 
213   /**
214    * @brief Get the most recently used workspace path
215    *
216    * @return The filepath to the last recently used workspace (may be invalid)
217    */
218   static FilePath getMostRecentlyUsedWorkspacePath() noexcept;
219 
220   /**
221    * @brief Set the most recently used workspace path
222    *
223    * @param path  The filepath to the workspace directory
224    */
225   static void setMostRecentlyUsedWorkspacePath(const FilePath& path) noexcept;
226 
227   /**
228    * @brief Current workspace file format version (constant)
229    *
230    * @warning Don't change this value unless you know exactly what you're doing!
231    *
232    * @return File format version
233    */
FILE_FORMAT_VERSION()234   static Version FILE_FORMAT_VERSION() noexcept {
235     return Version::fromString("0.1");
236   }
237 
238 private:  // Data
239   /// a FilePath object which represents the workspace directory
240   FilePath mPath;
241 
242   /// the directory "projects"
243   FilePath mProjectsPath;
244 
245   /// the subdirectory of the current file format version
246   FilePath mMetadataPath;
247 
248   /// the directory "v#/libraries"
249   FilePath mLibrariesPath;
250 
251   /// to lock the version directory (#mMetadataPath)
252   DirectoryLock mLock;
253 
254   /// the WorkspaceSettings object
255   QScopedPointer<WorkspaceSettings> mWorkspaceSettings;
256 
257   /// the library database
258   QScopedPointer<WorkspaceLibraryDb> mLibraryDb;
259 
260   /// a tree model for the whole projects directory
261   QScopedPointer<ProjectTreeModel> mProjectTreeModel;
262 
263   /// a list model of all recent projects
264   QScopedPointer<RecentProjectsModel> mRecentProjectsModel;
265 
266   /// a list model of all favorite projects
267   QScopedPointer<FavoriteProjectsModel> mFavoriteProjectsModel;
268 };
269 
270 /*******************************************************************************
271  *  End of File
272  ******************************************************************************/
273 
274 }  // namespace workspace
275 }  // namespace librepcb
276 
277 #endif  // LIBREPCB_WORKSPACE_H
278