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_PROJECT_PROJECT_H 21 #define LIBREPCB_PROJECT_PROJECT_H 22 23 /******************************************************************************* 24 * Includes 25 ******************************************************************************/ 26 #include <librepcb/common/attributes/attribute.h> 27 #include <librepcb/common/attributes/attributeprovider.h> 28 #include <librepcb/common/elementname.h> 29 #include <librepcb/common/exceptions.h> 30 #include <librepcb/common/fileio/directorylock.h> 31 #include <librepcb/common/fileio/transactionaldirectory.h> 32 #include <librepcb/common/uuid.h> 33 #include <librepcb/common/version.h> 34 35 #include <QtCore> 36 37 /******************************************************************************* 38 * Namespace / Forward Declarations 39 ******************************************************************************/ 40 class QPrinter; 41 42 namespace librepcb { 43 44 class StrokeFontPool; 45 46 namespace project { 47 48 class ProjectMetadata; 49 class ProjectSettings; 50 class ProjectLibrary; 51 class Circuit; 52 class Schematic; 53 class SchematicLayerProvider; 54 class ErcMsgList; 55 class Board; 56 57 /******************************************************************************* 58 * Class Project 59 ******************************************************************************/ 60 61 /** 62 * @brief The Project class represents a whole (opened) project with all its 63 * content 64 * 65 * This class represents a whole project with all the content of its directory: 66 * - circuit, schematics and boards 67 * - the project's library 68 * - project settings 69 * - and much more... 70 * 71 * The constructor of the ::librepcb::project::Project class needs the filepath 72 * to a project file. Then the project will be opened. A new project can be 73 * created with the static method #create(). The destructor will close the 74 * project (without saving). Use the method #save() to write the whole project 75 * to the harddisc. 76 * 77 * @note !! A detailed description about projects is available here: @ref 78 * doc_project !! 79 */ 80 class Project final : public QObject, public AttributeProvider { 81 Q_OBJECT 82 83 public: 84 // Constructors / Destructor 85 Project() = delete; 86 Project(const Project& other) = delete; 87 88 /** 89 * @brief The constructor to open an existing project with all its content 90 * 91 * @param directory The directory which contains the project. 92 * @param filename The filename of the *.lpp project file. 93 * 94 * @throw Exception If the project could not be opened successfully 95 */ Project(std::unique_ptr<TransactionalDirectory> directory,const QString & filename)96 Project(std::unique_ptr<TransactionalDirectory> directory, 97 const QString& filename) 98 : Project(std::move(directory), filename, false) {} 99 100 /** 101 * @brief The destructor will close the whole project (without saving!) 102 */ 103 ~Project() noexcept; 104 105 // Getters: General 106 107 /** 108 * @brief Get the filepath of the project file (*.lpp) 109 * 110 * @return The absolute filepath 111 */ getFilepath()112 FilePath getFilepath() const noexcept { 113 return mDirectory->getAbsPath(mFilename); 114 } 115 116 /** 117 * @brief Get the path to the project directory 118 * 119 * @return The filepath to the project directory 120 */ getPath()121 FilePath getPath() const noexcept { return mDirectory->getAbsPath(); } 122 getDirectory()123 const TransactionalDirectory& getDirectory() const noexcept { 124 return *mDirectory; 125 } 126 getDirectory()127 TransactionalDirectory& getDirectory() noexcept { return *mDirectory; } 128 129 /** 130 * @brief Get the StrokeFontPool which contains all stroke fonts of the 131 * project 132 * 133 * @return A reference to the librepcb::StrokeFontPool object 134 */ getStrokeFonts()135 StrokeFontPool& getStrokeFonts() const noexcept { return *mStrokeFontPool; } 136 137 /** 138 * @brief Get the ProjectMetadata object which contains all project metadata 139 * 140 * @return A reference to the ProjectMetadata object 141 */ getMetadata()142 ProjectMetadata& getMetadata() const noexcept { return *mProjectMetadata; } 143 144 /** 145 * @brief Get the ProjectSettings object which contains all project settings 146 * 147 * @return A reference to the ProjectSettings object 148 */ getSettings()149 ProjectSettings& getSettings() const noexcept { return *mProjectSettings; } 150 151 /** 152 * @brief Get the ProjectLibrary object which contains all library elements 153 * used in this project 154 * 155 * @return A reference to the ProjectLibrary object 156 */ getLibrary()157 ProjectLibrary& getLibrary() const noexcept { return *mProjectLibrary; } 158 159 /** 160 * @brief Get the ERC messages list 161 * 162 * @return A reference to the ErcMsgList object 163 */ getErcMsgList()164 ErcMsgList& getErcMsgList() const noexcept { return *mErcMsgList; } 165 166 /** 167 * @brief Get the Circuit object 168 * 169 * @return A reference to the Circuit object 170 */ getCircuit()171 Circuit& getCircuit() const noexcept { return *mCircuit; } 172 173 // Schematic Methods 174 getLayers()175 SchematicLayerProvider& getLayers() noexcept { 176 return *mSchematicLayerProvider; 177 } getLayers()178 const SchematicLayerProvider& getLayers() const noexcept { 179 return *mSchematicLayerProvider; 180 } 181 182 /** 183 * @brief Get the page index of a specific schematic 184 * 185 * @return the schematic index (-1 if the schematic does not exist) 186 */ 187 int getSchematicIndex(const Schematic& schematic) const noexcept; 188 189 /** 190 * @brief Get all schematics 191 * 192 * @return A QList with all schematics 193 */ getSchematics()194 const QList<Schematic*>& getSchematics() const noexcept { 195 return mSchematics; 196 } 197 198 /** 199 * @brief Get the schematic page at a specific index 200 * 201 * @param index The page index (zero is the first) 202 * 203 * @return A pointer to the specified schematic, or nullptr if index is 204 * invalid 205 */ getSchematicByIndex(int index)206 Schematic* getSchematicByIndex(int index) const noexcept { 207 return mSchematics.value(index, nullptr); 208 } 209 210 /** 211 * @brief Get the schematic page with a specific UUID 212 * 213 * @param uuid The schematic UUID 214 * 215 * @return A pointer to the specified schematic, or nullptr if uuid is invalid 216 */ 217 Schematic* getSchematicByUuid(const Uuid& uuid) const noexcept; 218 219 /** 220 * @brief Get the schematic page with a specific name 221 * 222 * @param name The schematic name 223 * 224 * @return A pointer to the specified schematic, or nullptr if name is invalid 225 */ 226 Schematic* getSchematicByName(const QString& name) const noexcept; 227 228 /** 229 * @brief Create a new schematic (page) 230 * 231 * @param name The schematic page name 232 * 233 * @return A pointer to the new schematic 234 * 235 * @throw Exception This method throws an exception on error. 236 */ 237 Schematic* createSchematic(const ElementName& name); 238 239 /** 240 * @brief Add an existing schematic to this project 241 * 242 * @param schematic The schematic to add 243 * @param newIndex The desired index in the list (after inserting it) 244 * 245 * @throw Exception On error 246 * 247 * @undocmd{::librepcb::project::CmdSchematicAdd} 248 */ 249 void addSchematic(Schematic& schematic, int newIndex = -1); 250 251 /** 252 * @brief Remove a schematic from this project 253 * 254 * @param schematic The schematic to remove 255 * @param deleteSchematic If true, the schematic object will be deleted 256 * (Set this to true only when called from ctor or 257 * dtor!!) 258 * 259 * @throw Exception On error 260 * 261 * @undocmd{::librepcb::project::CmdSchematicRemove} 262 */ 263 void removeSchematic(Schematic& schematic, bool deleteSchematic = false); 264 265 /** 266 * @brief Export the schematic pages as a PDF 267 * 268 * @param filepath The filepath where the PDF should be saved. If the file 269 * exists already, it will be overwritten. 270 * 271 * @throw Exception On error 272 */ 273 void exportSchematicsAsPdf(const FilePath& filepath); 274 275 /** 276 * @brief Print some schematics to a QPrinter (printer or file) 277 * 278 * @param printer The QPrinter where to print the schematic pages 279 * @param pages A list with all schematic page indexes which should be 280 * printed 281 * 282 * @throw Exception On error 283 */ 284 void printSchematicPages(QPrinter& printer, QList<int>& pages); 285 286 // Board Methods 287 288 /** 289 * @brief Get the index of a specific board 290 * 291 * @return the board index (-1 if the board does not exist) 292 */ 293 int getBoardIndex(const Board& board) const noexcept; 294 295 /** 296 * @brief Get all boards 297 * 298 * @return A QList with all boards 299 */ getBoards()300 const QList<Board*>& getBoards() const noexcept { return mBoards; } 301 302 /** 303 * @brief Get the board at a specific index 304 * 305 * @param index The board index (zero is the first) 306 * 307 * @return A pointer to the specified board, or nullptr if index is invalid 308 */ getBoardByIndex(int index)309 Board* getBoardByIndex(int index) const noexcept { 310 return mBoards.value(index, nullptr); 311 } 312 313 /** 314 * @brief Get the board with a specific UUID 315 * 316 * @param uuid The board UUID 317 * 318 * @return A pointer to the specified board, or nullptr if uuid is invalid 319 */ 320 Board* getBoardByUuid(const Uuid& uuid) const noexcept; 321 322 /** 323 * @brief Get the board with a specific name 324 * 325 * @param name The board name 326 * 327 * @return A pointer to the specified board, or nullptr if name is invalid 328 */ 329 Board* getBoardByName(const QString& name) const noexcept; 330 331 /** 332 * @brief Create a new board 333 * 334 * @param name The board name 335 * 336 * @return A pointer to the new board 337 * 338 * @throw Exception This method throws an exception on error. 339 */ 340 Board* createBoard(const ElementName& name); 341 342 /** 343 * @brief Create a new board as a copy of an existing board 344 * 345 * @param other The board to copy 346 * @param name The board name 347 * 348 * @return A pointer to the new board 349 * 350 * @throw Exception This method throws an exception on error. 351 */ 352 Board* createBoard(const Board& other, const ElementName& name); 353 354 /** 355 * @brief Add an existing board to this project 356 * 357 * @param board The board to add 358 * @param newIndex The desired index in the list (after inserting it) 359 * 360 * @throw Exception On error 361 * 362 * @undocmd{::librepcb::project::CmdBoardAdd} 363 */ 364 void addBoard(Board& board, int newIndex = -1); 365 366 /** 367 * @brief Remove a board from this project 368 * 369 * @param board The board to remove 370 * @param deleteBoard If true, the board object will be deleted 371 * (Set this to true only when called from ctor or 372 * dtor!!) 373 * 374 * @throw Exception On error 375 * 376 * @undocmd{::librepcb::project::CmdBoardRemove} 377 */ 378 void removeBoard(Board& board, bool deleteBoard = false); 379 380 // General Methods 381 382 /** 383 * @brief Save the project to the transactional file system 384 * 385 * @throw Exception If an error occurred. 386 */ 387 void save(); 388 389 // Inherited from AttributeProvider 390 /// @copydoc librepcb::AttributeProvider::getUserDefinedAttributeValue() 391 QString getUserDefinedAttributeValue(const QString& key) const 392 noexcept override; 393 /// @copydoc librepcb::AttributeProvider::getBuiltInAttributeValue() 394 QString getBuiltInAttributeValue(const QString& key) const noexcept override; 395 396 // Operator Overloadings 397 bool operator==(const Project& rhs) noexcept { return (this == &rhs); } 398 bool operator!=(const Project& rhs) noexcept { return (this != &rhs); } 399 400 // Static Methods 401 create(std::unique_ptr<TransactionalDirectory> directory,const QString & filename)402 static Project* create(std::unique_ptr<TransactionalDirectory> directory, 403 const QString& filename) { 404 return new Project(std::move(directory), filename, true); 405 } 406 407 static bool isFilePathInsideProjectDirectory(const FilePath& fp) noexcept; 408 static bool isProjectFile(const FilePath& file) noexcept; 409 static bool isProjectDirectory(const FilePath& dir) noexcept; 410 static Version getProjectFileFormatVersion(const FilePath& dir); 411 412 signals: 413 414 /// @copydoc AttributeProvider::attributesChanged() 415 void attributesChanged() override; 416 417 /** 418 * @brief This signal is emitted after a schematic was added to the project 419 * 420 * @param newIndex The index of the added schematic 421 */ 422 void schematicAdded(int newIndex); 423 424 /** 425 * @brief This signal is emitted after a schematic was removed from the 426 * project 427 * 428 * @param oldIndex The index of the removed schematic 429 */ 430 void schematicRemoved(int oldIndex); 431 432 /** 433 * @brief This signal is emitted after a board was added to the project 434 * 435 * @param newIndex The index of the added board 436 */ 437 void boardAdded(int newIndex); 438 439 /** 440 * @brief This signal is emitted after a board was removed from the project 441 * 442 * @param oldIndex The index of the removed board 443 */ 444 void boardRemoved(int oldIndex); 445 446 private: 447 // Private Methods 448 449 /** 450 * @brief The constructor to create or open a project with all its content 451 * 452 * @param directory The directory which contains the project. 453 * @param filename The filename of the *.lpp project file. 454 * @param create True if the specified project does not exist already 455 * and must be created. 456 * 457 * @throw Exception If the project could not be created/opened 458 * successfully 459 * 460 * @todo Remove interactive message boxes, should be done at a higher layer! 461 */ 462 explicit Project(std::unique_ptr<TransactionalDirectory> directory, 463 const QString& filename, bool create); 464 465 std::unique_ptr<TransactionalDirectory> mDirectory; 466 QString mFilename; ///< the name of the *.lpp project file 467 468 // General 469 QScopedPointer<StrokeFontPool> 470 mStrokeFontPool; ///< all fonts from ./resources/fontobene/ 471 QScopedPointer<ProjectMetadata> 472 mProjectMetadata; ///< e.g. project name, author, ... 473 QScopedPointer<ProjectSettings> 474 mProjectSettings; ///< all project specific settings 475 QScopedPointer<ProjectLibrary> 476 mProjectLibrary; ///< the library which contains all elements needed in 477 ///< this project 478 QScopedPointer<ErcMsgList> 479 mErcMsgList; ///< A list which contains all electrical rule check (ERC) 480 ///< messages 481 QScopedPointer<Circuit> 482 mCircuit; ///< The whole circuit of this project (contains all 483 ///< netclasses, netsignals, component instances, ...) 484 QList<Schematic*> mSchematics; ///< All schematics of this project 485 QList<Schematic*> 486 mRemovedSchematics; ///< All removed schematics of this project 487 QScopedPointer<SchematicLayerProvider> 488 mSchematicLayerProvider; ///< All schematic layers of this project 489 QList<Board*> mBoards; ///< All boards of this project 490 QList<Board*> mRemovedBoards; ///< All removed boards of this project 491 QScopedPointer<AttributeList> 492 mAttributes; ///< all attributes in a specific order 493 }; 494 495 /******************************************************************************* 496 * End of File 497 ******************************************************************************/ 498 499 } // namespace project 500 } // namespace librepcb 501 502 #endif // LIBREPCB_PROJECT_PROJECT_H 503