From 2e2ccb7ffcdcb68c8a7f20ce173358d62f2a62f7 Mon Sep 17 00:00:00 2001 From: Markus Date: Wed, 9 Apr 2025 13:30:59 +0200 Subject: [PATCH] v1.17.0: Change gloabl setting to project level settings to sync syttings with projects --- .prjctmngr | Bin 0 -> 905 bytes ProjektManager.pro | 10 +- ProjektManager_resource.rc | 2 +- icons/appSymbol - Kopie.png.ico | Bin 0 -> 270398 bytes icons/appSymbol.png.ico | Bin 0 -> 270398 bytes installer/config/config.xml | 4 +- .../meta/installscript.qs | 4 +- .../de.ProjektManager.main/meta/package.xml | 4 +- src/mainsettingsdialog.h | 2 + src/mainwindow.cpp | 44 ++- src/mainwindow.h | 1 + src/newprojektdialog.cpp | 21 +- src/projektdata.cpp | 317 +++++++++++++++--- src/projektdata.h | 142 ++------ 14 files changed, 358 insertions(+), 193 deletions(-) create mode 100644 .prjctmngr create mode 100644 icons/appSymbol - Kopie.png.ico create mode 100644 icons/appSymbol.png.ico diff --git a/.prjctmngr b/.prjctmngr new file mode 100644 index 0000000000000000000000000000000000000000..e4bc6b30a7ef9c1eab4252a03c895e466a0aeec6 GIT binary patch literal 905 zcmb7@Jx;?w5QX2ih>`*!kRoc>g@OhJB;*RjPYR%-F<=ps#Exu7f{Snn4!|X7xD74e zZcHMh$beRBduQJKyfgS|AClJ9Q=wdsN;FWVGsVi-51b49Z;G@p zrz@4gQu6IF1?UMjr*rI2MBZsgo{8?UHFG9dB5XZvFYp`@QxSQ|&dK3(HshN;wR^3` zfsf3~+Qq=Yz_w;PhHXjxn99SN^NOx(t|=X5>ga$it%5Az=`;eL;<22@Ea^mDl!);p zI&7`jC4P?VXi*2t4UK=F(yRJ#sOY2&({l8cGl_%_bKM3uBXmwVd+W~`w&@)Oz6o(D z{2bW|-We78!829D1wEQdI* -IDI_ICON1 ICON "C:/Users/Markus/Nextcloud/CPP-Projekte/AutoTools/ProjektManager/icons/appicon.ico" +IDI_ICON1 ICON "C:\\Users\\Markus\\Nextcloud\\Projekte\\CPP-Projekte\\AutoTools\\ProjektManager\\icons\\appicon.ico" VS_VERSION_INFO VERSIONINFO FILEVERSION 0,0,0,0 diff --git a/icons/appSymbol - Kopie.png.ico b/icons/appSymbol - Kopie.png.ico new file mode 100644 index 0000000000000000000000000000000000000000..394af270d76a4984c36b928767c36d8e00f0d0f4 GIT binary patch literal 270398 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
  • pU3tnqHn(%Y5Vim60*evl9hscE zJc@4{as6xzK* zHm5F+;@ejIza=n~yIi>b9(Nnt$0Vp+93egW%%Tzv*+n*|E|22dW?X+ihVs{ie@Wy* zpWSEVx9uDdQ~MtmzVv*n&o453#O(Fi2Bq5nh+>~FdanoDb~B*&rs%UXVq5I9Yi|*2 zV5IY7YX8kWV$k1g-(I#Mo{HMr#7&t1S`mP@~Hg#rxJ|fu_-pyruP@2*bJ_p3F`L(+wy(R zRC6{)zs(wP?Z@bIj8ET?$*$OR{K6PzBbpoXoM>O%#Qf`GTlhgs7R8C=L-7a6#D_&} zcL-Gs=Ismai}B7te$4QXgV=m=6Z5Z&ZQ%#4Ulb>jM|j_R7L8wbLk0l;0l|%~uKfuh zKX&*s5MNi!9P_VD0yzkU^xk4}M;k zF);Q5;L9t3{FGq*Oz`s{-afojrp$UCf>*SDkq=1T#-CSs{n_?V|0%$q%aMW!;(C8T z$UQpIJ(6$Z50#EfPp)zOJ};)}cMd+=?~743!MXZ-fs?XbA)EdV z+{Xp6?c+yM?rkXNUf~vaCpkvCa^YWW*+qx?{ejQ!eY{60|L*Rk79aYVT-V&L zv5?=S+%!Vp+bmzS`}_!b<70;!4v~SaXW;e{p{aq`z1EqwP`Q}b>@n{pUMN23>yMPr zyEG0qGB8I5LhCnWUhHRfng{*eaf;1Q*?*a1(it-uSTT@#e{M*f^(FhcA{e4SWzG=K z?CTpp<;cJg4E&cENvR>9tlpE7(%vM(KK&`!{ZbsGEE(7$1}>0T^mF-?da`BpK9n5o zpG1kRJEi}$98OUO8Q4+=v_4YmOJ(npnVZih`lQbQ@AJ&`%wbR+8JG+Mw-QhHWs5x* zJiJhZr+fJF(n7vaEg6^-16oHR=YeMxCMCoNecsjG3;RL!WMGaAJV1i}nrvNl_?iI- z(a#gRZ0pz`4`81r$N(8wEcCv=H_CQ{Z2C8;ZY$f6?Zsm3dfBd)?NLJ-rY$l+2FL&z zAOmE843GgbKnBPF86X2>fDDiUGC&5%02v?yWPl8i0Wv@a$N(8217v^VBQRzV_PxMS_hq+Y&(AL)UhV+Q^z~QKWFfL7k+vvUk^Xp zIPSK;!gn0;ogN3i=ko8&(!YB6k%l<8{S|(~!S9)I;JcQ8`>n!WKV0&?KDO4=K+mp? ztasFsK0(6Ob_74=0%cq)&4+8j?R(@kfIWmSqm-E&ZC?|%>ne8%t-*ITuuJ~dht_(V{H(##koVL_6W_Mu z>nU67ZAE_9B3kc^BR;u8?3hiTDX?sM+Fkl5*m1LU;c|sIZnjC{$4?#n>&nj|YQHpH z@-un7oj=L>;R;yAH*(ypP2KC7wf#S{Se!6h7rvhJc5fW@+4gAtIFEnA+hP4T27W{S z*KMhPonIMVzAidpa8vub7gS#|o|HLFE_BWYzPC7W?#x17ymhTFkr#jTW$Q@?-sD-7 z?l^FPjx|Qz_|bFwI%#G9p!%2fEzl8t+3Lpcy*Rgfu?Igbe}DA&u1o&ZFM zTwl|lkhjC#{)v}@pY-9o^28WFex!x3)wiVYxI}-{i|s}QL@!C$U-d;7G_J4aTT;E+R*Jv9(ct>(d zv(tsQs$dg8ySQMnqjKW*z4g7vQcE+U|LM{=(ezeF9r(!x*G00kAunVY2^YSMOX3jT zR9-}O%%*i?-jMAb;)nb;#nsq9x3484@-lRI{nySC*6~eTgv9BliOmkYkv_egq$#rW z?=`rtPigvziH+|luvn6yZxFliroLpFej*@vyZ)QEi{e@1fD4z%nke-RrX}AbPlD9Y zniFLgz9+Z_peIrr-;wcMxrk|&PIurM|E`|DWUoumlHXOk;+&j<&NY*4TQ|JECW213#;{awB*X zgC*a@rue?bD0{p9cV+z83ReynT2d#>CVHDQ(^6jbsE&3Mz0H|JPA`p~ZN|IeZ}YR{ zug#9+Rd`wFe;q%_pXTS}2EXn6>smQ@wI(GYO=M(ks@+|)K9<1he_4#H^(XjpeXZlV zew(#@us+vuUGloNoAtdXfvmxDU2iy9t-XDjY~f8^%YV(;zp1~q3A#MRcYXaJ`=)*^ zd`HIjWK3gRo}*^{8j6=IunXU9xIcGl8E3O#RPjOE zTj5Kdngw%!>B0UAU+#8y)HE);aP{l(3Ws8=pr7(1$q--90$ z2A#Ngw|aloZC|3(bN}YTGt+k$JG%N!cVoXVqGz4vwQ^3%y5HH5I~Y*aZuRHRy-)D> LAI#=KMF##K3FFD{ literal 0 HcmV?d00001 diff --git a/icons/appSymbol.png.ico b/icons/appSymbol.png.ico new file mode 100644 index 0000000000000000000000000000000000000000..394af270d76a4984c36b928767c36d8e00f0d0f4 GIT binary patch literal 270398 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
  • pU3tnqHn(%Y5Vim60*evl9hscE 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 LAI#=KMF##K3FFD{ literal 0 HcmV?d00001 diff --git a/installer/config/config.xml b/installer/config/config.xml index 6d098d4..2531cd1 100644 --- a/installer/config/config.xml +++ b/installer/config/config.xml @@ -3,6 +3,8 @@ ProjektManager 1.16.3 <Name>ProjektManager</Name> Installer + installerIcon1 + installerIcon2 Markus ProjektManager @ApplicationsDir@/ProjektManager/ @@ -11,7 +13,7 @@ ProjektManagerMaintenanceTool - https://code.obermui.de/Markus/ProjektManager/media/branch/main/installer/repository + https://code.obermui.de/Markus/ProjektManagerC/media/branch/main/installer/repository 1 Main-Repo diff --git a/installer/packages/de.ProjektManager.main/meta/installscript.qs b/installer/packages/de.ProjektManager.main/meta/installscript.qs index ed7ced1..8a0924c 100644 --- a/installer/packages/de.ProjektManager.main/meta/installscript.qs +++ b/installer/packages/de.ProjektManager.main/meta/installscript.qs @@ -6,9 +6,9 @@ Component.prototype.createOperations = function() { component.createOperations(); if(systemInfo.productType === "windows") { - component.addOperation("CreateShortcut", "@TargetDir@/bin/ProjektManager.exe", "@StartMenuDir@/ProjektManager.lnk", "description="); + component.addOperation("CreateShortcut", "@TargetDir@/bin/ProjektManager.exe", "@StartMenuDir@/ProjektManager.lnk", "description=aaaaa"); - component.addOperation("CreateShortcut", "@TargetDir@/bin/ProjektManager.exe", "@HomeDir@/Desktop/ProjektManager.lnk", "description="); + component.addOperation("CreateShortcut", "@TargetDir@/bin/ProjektManager.exe", "@HomeDir@/Desktop/ProjektManager.lnk", "description=aaaaa"); } } diff --git a/installer/packages/de.ProjektManager.main/meta/package.xml b/installer/packages/de.ProjektManager.main/meta/package.xml index eb79154..8cb8176 100644 --- a/installer/packages/de.ProjektManager.main/meta/package.xml +++ b/installer/packages/de.ProjektManager.main/meta/package.xml @@ -1,10 +1,10 @@ ProjektManager 1.16.3 - + aaaaa 1.16.3 true - 2025-01-16 + 2025-04-09 @TargetDir@/bin/ diff --git a/src/mainsettingsdialog.h b/src/mainsettingsdialog.h index 489bc02..75b44c4 100644 --- a/src/mainsettingsdialog.h +++ b/src/mainsettingsdialog.h @@ -6,6 +6,8 @@ #include "stylehandler.h" #include "switch.h" + + namespace Ui { class MainSettingsDialog; } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 20c7edb..30649d5 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -59,14 +59,16 @@ MainWindow::MainWindow(QWidget *parent) ueberdialog->setPixmap("://icons/appicon.ico"); updater = ueberdialog->updater(); mainsettingsDialog = new MainSettingsDialog(ueberdialog->styleHandler()); - projects = new ProjektDataList(settingsPath); + + + // Initialize ProjektDataList with company and app name + projects = new ProjektDataList("M$RKUS", appName); projects->load(); reloadEntryList(); statDialog = new StatisticsDialog(projects); - //START cleanup... QString autoremdir = MainSettingsDialog::getAutoRemoveDir(); if(!autoremdir.isEmpty() && QDir(autoremdir).exists()) { @@ -112,8 +114,10 @@ void MainWindow::createNewProjektEntry() if(npd->exec() == QDialog::Accepted) { auto data = npd->getProjektStruct(projects); createNewtask(CREATE_NEW_PROJECT, data); - projects->append(data); - projects->store(); + + // Use addProject to handle both adding to list and saving to file + projects->addProject(data); + addProjectToListWidget(data); } @@ -166,18 +170,13 @@ void MainWindow::on_pushButton_rm_clicked() { qDebug() << "ui->listWidget->currentRow(): " << ui->listWidget->currentRow() << "\nui->listWidget->selectedItems()" << ui->listWidget->selectedItems(); if (ui->listWidget->currentRow() != -1) { - // Löschen des ausgewählten Elements - auto item = ui->listWidget->takeItem(ui->listWidget->currentRow()); + // Get the selected item and its ID + auto item = ui->listWidget->item(ui->listWidget->currentRow()); size_t id = item->data(187).toULongLong(); - for(int i = 0; i < projects->size(); i++) { - if(projects->at(i)->getId() == id) { - projects->removeAt(i); - projects->store(); - break; - } - } - delete item; + // Remove from list and delete from UI + projects->removeProject(id); + delete ui->listWidget->takeItem(ui->listWidget->currentRow()); } } @@ -210,8 +209,10 @@ void MainWindow::projectSettings_clicked(unsigned long long id) connect(npd, SIGNAL(removeClicked(unsigned long long)), this, SLOT(projectSettings_remove_clicked(unsigned long long))); if(npd->exec() == QDialog::Accepted) { auto data = npd->getProjektStruct(projects); - projects->replace(i, data); - projects->store(); + + // Replace project at index i with the updated data + projects->replaceProject(i, data); + reloadEntryList(); createNewtask(S_TASK::UPDATE_PROJECT_DATA, data); } @@ -229,14 +230,9 @@ void MainWindow::projectSettings_remove_clicked(unsigned long long id) break; } } - for(int i = 0; i < projects->size(); i++) { - if(projects->at(i)->getId() == id) { - projects->removeAt(i); - projects->store(); - break; - } - } + // Remove from project list and save changes + projects->removeProject(id); } void MainWindow::on_actionAuf_Updates_pr_fen_triggered() @@ -287,3 +283,5 @@ void MainWindow::on_actionListe_Aktualiseren_triggered() reloadEntryList(); } + + diff --git a/src/mainwindow.h b/src/mainwindow.h index 0a96b4e..4621127 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -75,5 +75,6 @@ public: // QWidget interface protected: void closeEvent(QCloseEvent *event); + }; #endif // MAINWINDOW_H diff --git a/src/newprojektdialog.cpp b/src/newprojektdialog.cpp index 82a13a5..27bcc87 100644 --- a/src/newprojektdialog.cpp +++ b/src/newprojektdialog.cpp @@ -104,7 +104,6 @@ void NewProjektDialog::loadSettingsFromProjektData(ProjektData *projektData) { this->id = projektData->getId(); } - ProjektData *NewProjektDialog::getProjektStruct(ProjektDataList *projektDataParent) { QString name = ui->lineEditProjektName->text(); @@ -158,17 +157,21 @@ ProjektData *NewProjektDialog::getProjektStruct(ProjektDataList *projektDataPare // Erstelle ein ProjektData Objekt mit den extrahierten Informationen ProjektData *projektData = new ProjektData(name, path, id, qt_installer_name, qt_installer_version, qt_installer_titel, - qt_installer_publisher, qt_installer_start_menue_dir, qt_installer_online_repo_url, - qt_installer_package_name, qt_installer_description, qt_installer_updater_icon_path, - qt_installer_online_repo, qt_installer_start_menue_link, qt_installer_desktop_link, - qt_installer_gpl3_licence, qt_m_updater_lib, false, - qt_move_files_to_src_sub_dir, qt_app_icon, qt_installer_start_after_install, qt_app_icon_path, - git_init, git_enable_daily_auto_commit, git_init_readme, git_add_git_ignore, - git_set_remote_repo, remote_repo_url, qt_installer, readmeinittext, git_overwriteReadmeFile, lineEditVersionFile, - git_lfs); + qt_installer_publisher, qt_installer_start_menue_dir, qt_installer_online_repo_url, + qt_installer_package_name, qt_installer_description, qt_installer_updater_icon_path, + qt_installer_online_repo, qt_installer_start_menue_link, qt_installer_desktop_link, + qt_installer_gpl3_licence, qt_m_updater_lib, false, + qt_move_files_to_src_sub_dir, qt_app_icon, qt_installer_start_after_install, qt_app_icon_path, + git_init, git_enable_daily_auto_commit, git_init_readme, git_add_git_ignore, + git_set_remote_repo, remote_repo_url, qt_installer, readmeinittext, git_overwriteReadmeFile, lineEditVersionFile, + git_lfs); projektData->setParentList(projektDataParent); + + // Save the new project to its own file + projektData->save(); + return projektData; } diff --git a/src/projektdata.cpp b/src/projektdata.cpp index 1dcf155..c9098e3 100644 --- a/src/projektdata.cpp +++ b/src/projektdata.cpp @@ -3,6 +3,7 @@ #include "qdir.h" #include "qprocess.h" #include +#include "mainsettingsdialog.h" ProjektData::ProjektData(QString version) @@ -69,11 +70,185 @@ ProjektData::ProjektData(QString name, QString path, size_t id, QString qt_insta } +// Convert an absolute path to a portable relative path +QString ProjektData::toPortablePath(const QString& absolutePath) const +{ + if (absolutePath.isEmpty()) + return absolutePath; + + QString projectDir = getProjectDirPath(); + + // Check if path is within the project directory + if (absolutePath.startsWith(projectDir)) { + // Make it relative to project directory + return QDir(projectDir).relativeFilePath(absolutePath); + } + + // If not within project dir, just return the absolute path + // (this will be converted back when loaded) + return absolutePath; +} + +// Convert a portable path back to an absolute path +QString ProjektData::toAbsolutePath(const QString& portablePath) const +{ + if (portablePath.isEmpty()) + return portablePath; + + QString projectDir = getProjectDirPath(); + + // Check if it's already an absolute path + QFileInfo fileInfo(portablePath); + if (fileInfo.isAbsolute()) + return portablePath; + + // If it's relative, make it absolute relative to the project directory + return QDir(projectDir).absoluteFilePath(portablePath); +} + + +QString ProjektData::getConfigFilePath() const +{ + QFileInfo fileInfo(this->path); + return fileInfo.absolutePath() + "/.prjctmngr"; +} + + +bool ProjektData::save() +{ + QFile file(getConfigFilePath()); + + if (file.open(QIODevice::WriteOnly)) { + QDataStream out(&file); + + // Write version information + out << DATA_VERSION; + + // Write project data + writeToStream(out); + + file.close(); + qDebug() << "Project data saved to" << getConfigFilePath(); + return true; + } else { + qWarning() << "Failed to open file for writing:" << getConfigFilePath(); + return false; + } +} + +ProjektData* ProjektData::load(const QString& projectPath) +{ + QFileInfo fileInfo(projectPath); + QString configPath = fileInfo.absolutePath() + "/.prjctmngr"; + QString projectDir = fileInfo.absolutePath(); + + QFile file(configPath); + + if (!file.exists()) { + qWarning() << "Project config file does not exist:" << configPath; + return nullptr; + } + + if (file.open(QIODevice::ReadOnly)) { + QDataStream in(&file); + + // Read version information + QString version; + in >> version; + + // Create a new project data object with the right version and project directory + ProjektData* data = readFromStream(in, projectDir); + + file.close(); + + if (data) { + qDebug() << "Project data loaded from" << configPath; + } + + return data; + } else { + qWarning() << "Failed to open file for reading:" << configPath; + return nullptr; + } +} + + +void ProjektData::writeToStream(QDataStream& out) const +{ + // Save the absolute path in QSettings, but store a portable path in the project file + // The project file path will always be absolute when loaded back + + out << magicNumber + << name << path << id; + + // Serialize all data members - convert paths to portable format where needed + out << qt_installer_name << qt_installer_version << toPortablePath(qt_installer_versionFile) + << qt_installer_titel << qt_installer_publisher << qt_installer_start_menue_dir + << qt_installer_online_repo_url << qt_installer_package_name << qt_installer_description + << toPortablePath(qt_installer_updater_icon_path) << qt_installer_online_repo + << qt_installer_start_menue_link << qt_installer_desktop_link + << qt_installer_gpl3_licence << qt_m_updater_lib << qt_remove_shadow_build_setting + << qt_move_files_to_src_sub_dir << qt_app_icon << qt_installer_start_after_install + << toPortablePath(qt_app_icon_path) << git_init << git_enable_daily_auto_commit << git_init_readme + << git_add_git_ignore << git_set_remote_repo << remote_repo_url << qt_installer << readme_init_text + << git_overwriteReadmeFile << git_lfs; +} + + +ProjektData* ProjektData::readFromStream(QDataStream& in, const QString& projectDir) +{ + ProjektData* data = new ProjektData(DATA_VERSION); + + in >> data->magicNumber; + + // Deserialize basic data members + in >> data->name >> data->path >> data->id; + + // Deserialize all other data members - convert paths from portable to absolute where needed + QString portableVersionFile, portableUpdaterIconPath, portableAppIconPath; + + in >> data->qt_installer_name >> data->qt_installer_version >> portableVersionFile + >> data->qt_installer_titel >> data->qt_installer_publisher >> data->qt_installer_start_menue_dir + >> data->qt_installer_online_repo_url >> data->qt_installer_package_name >> data->qt_installer_description + >> portableUpdaterIconPath >> data->qt_installer_online_repo >> data->qt_installer_start_menue_link + >> data->qt_installer_desktop_link >> data->qt_installer_gpl3_licence >> data->qt_m_updater_lib + >> data->qt_remove_shadow_build_setting >> data->qt_move_files_to_src_sub_dir >> data->qt_app_icon + >> data->qt_installer_start_after_install >> portableAppIconPath >> data->git_init + >> data->git_enable_daily_auto_commit >> data->git_init_readme >> data->git_add_git_ignore + >> data->git_set_remote_repo >> data->remote_repo_url >> data->qt_installer + >> data->readme_init_text >> data->git_overwriteReadmeFile >> data->git_lfs; + + // Convert portable paths to absolute paths + QDir dir(projectDir); + + // Convert version file path + data->qt_installer_versionFile = QFileInfo(portableVersionFile).isAbsolute() ? + portableVersionFile : dir.absoluteFilePath(portableVersionFile); + + // Convert updater icon path + data->qt_installer_updater_icon_path = QFileInfo(portableUpdaterIconPath).isAbsolute() ? + portableUpdaterIconPath : dir.absoluteFilePath(portableUpdaterIconPath); + + // Convert app icon path + data->qt_app_icon_path = QFileInfo(portableAppIconPath).isAbsolute() ? + portableAppIconPath : dir.absoluteFilePath(portableAppIconPath); + + // Check if data is valid + if (!data->dataValid()) { + delete data; + return nullptr; + } + + return data; +} + + + bool ProjektData::dataValid() const { return magicNumber == MAGIC_NUM; } -QString ProjektData::getProjectDirPath() +QString ProjektData::getProjectDirPath() const { QFileInfo fileInfo(this->path); return fileInfo.absolutePath() + "/"; @@ -174,7 +349,7 @@ size_t ProjektData::countLinesOfCode(ProjektData *data) // qDebug() << data->getAppName() << ": Line: " << zeilen; return zeilen; } -#include "mainsettingsdialog.h" + size_t ProjektData::countGitCommits( ProjektData *data) { @@ -380,69 +555,123 @@ bool ProjektData::getGit_lfs() const } + +// ProjektDataList implementation + +ProjektDataList::ProjektDataList(const QString& company, const QString& appName) + : company(company), appName(appName) +{ + qDebug() << " ProjektDataList()"; +} + ProjektDataList::~ProjektDataList() { - if(!this->settingsPath.isEmpty()) - this->store(); + // Store projects before destruction + this->store(); + // Clean up project data while(this->size()) delete this->takeAt(0); qDebug() << " ~ProjektDataList()"; } -ProjektDataList::ProjektDataList(QString settingsPath) - : settingsPath(settingsPath) +bool ProjektDataList::store() { - qDebug() << " ProjektDataList()"; -} + QSettings settings(company, appName); -bool ProjektDataList::store() { - return store(this->settingsPath); -} - -bool ProjektDataList::store(QString path) { - if(path.isEmpty()) - return false; - QFile file(path); - - if (file.open(QIODevice::WriteOnly)) { - QDataStream out(&file); - out << *this; - file.close(); - } else { - return false; + // Create a list of project paths + QStringList projectPaths; + for (ProjektData* project : *this) { + projectPaths.append(project->getPath()); } + // Store the paths in QSettings + settings.setValue("ProjectPaths", projectPaths); + + qDebug() << "Stored" << projectPaths.size() << "project paths to QSettings"; return true; } -bool ProjektDataList::load() { - return load(this->settingsPath); +bool ProjektDataList::load() +{ + // Clear the current list + while(this->size()) + delete this->takeAt(0); -} + QSettings settings(company, appName); -bool ProjektDataList::load(QString path) { - if(path.isEmpty()) - return false; - QFile file(path); + // Get the list of project paths + QStringList projectPaths = settings.value("ProjectPaths").toStringList(); - if (file.open(QIODevice::ReadOnly)) { - QDataStream in(&file); - in >> *this; - file.close(); - } else { - return false; - } - - // Validate loaded data and remove invalid items - for(int i = 0; i < this->length(); i++) { - if(!this->at(i)->dataValid()) { - this->remove(i--); + // Load each project + for (const QString& path : projectPaths) { + QFileInfo fileInfo(path); + if (fileInfo.exists()) { + ProjektData* project = ProjektData::load(path); + if (project) { + project->setParentList(this); + this->append(project); + } } - else - this->at(i)->setParentList(this); } + qDebug() << "Loaded" << this->size() << "projects from QSettings"; return true; } + +void ProjektDataList::addProject(ProjektData* project) +{ + // Add to the list + project->setParentList(this); + this->append(project); + + // Save the project to its own file + project->save(); + + // Update the list of paths in QSettings + this->store(); +} + +bool ProjektDataList::removeProject(ProjektData* project) +{ + for (int i = 0; i < this->size(); i++) { + if (this->at(i) == project) { + return removeProject(i); + } + } + return false; +} + +bool ProjektDataList::removeProject(size_t id) +{ + for (int i = 0; i < this->size(); i++) { + if (this->at(i)->getId() == id) { + return removeProject(i); + } + } + return false; +} + +bool ProjektDataList::removeProject(int index) +{ + if (index >= 0 && index < this->size()) { + delete this->takeAt(index); + this->store(); + return true; + } + return false; +} + +bool ProjektDataList::replaceProject(int index, ProjektData* newProject) +{ + if (index >= 0 && index < this->size()) { + delete this->at(index); + this->replace(index, newProject); + newProject->setParentList(this); + newProject->save(); + this->store(); + return true; + } + return false; +} diff --git a/src/projektdata.h b/src/projektdata.h index 966ea57..89e92b3 100644 --- a/src/projektdata.h +++ b/src/projektdata.h @@ -5,13 +5,15 @@ #include #include #include - +#include +#include +#include class ProjektDataList; -#define DATA_VERSION QString("1.4.0") +#define DATA_VERSION QString("1.5.0") @@ -33,75 +35,19 @@ public: bool git_overwriteReadmeFile, QString qt_installer_versionFile, bool gitlfs, QString version = DATA_VERSION); - friend QDataStream &operator<<(QDataStream &out, const ProjektData &obj) { - out << obj.MAGIC_NUM - << obj.name << obj.path << obj.id; + // Save project data to a .prjctmngr file in the project directory + bool save(); - // Hier serialisieren Sie alle zusätzlichen Datenmember - out << obj.qt_installer_name << obj.qt_installer_version << obj.qt_installer_titel - << obj.qt_installer_publisher << obj.qt_installer_start_menue_dir << obj.qt_installer_online_repo_url - << obj.qt_installer_package_name << obj.qt_installer_description << obj.qt_installer_updater_icon_path - << obj.qt_installer_online_repo << obj.qt_installer_start_menue_link << obj.qt_installer_desktop_link - << obj.qt_installer_gpl3_licence << obj.qt_m_updater_lib << obj.qt_remove_shadow_build_setting - << obj.qt_move_files_to_src_sub_dir << obj.qt_app_icon << obj.qt_installer_start_after_install - << obj.qt_app_icon_path << obj.git_init << obj.git_enable_daily_auto_commit << obj.git_init_readme - << obj.git_add_git_ignore << obj.git_set_remote_repo << obj.remote_repo_url << obj.qt_installer << obj.readme_init_text - << obj.git_overwriteReadmeFile << obj.git_lfs << obj.qt_installer_versionFile; + // Load project data from a .prjctmngr file + static ProjektData* load(const QString& projectPath); - return out; - } - - friend QDataStream &operator>>(QDataStream &in, ProjektData &obj) { + // Get the path to the .prjctmngr file for this project + QString getConfigFilePath() const; - if(obj.data_version == DATA_VERSION) { - in >> obj.magicNumber; - // Hier deserialisieren Sie alle zusätzlichen Datenmember - in >> obj.name >> obj.path >> obj.id - >> obj.qt_installer_name >> obj.qt_installer_version >> obj.qt_installer_titel - >> obj.qt_installer_publisher >> obj.qt_installer_start_menue_dir >> obj.qt_installer_online_repo_url - >> obj.qt_installer_package_name >> obj.qt_installer_description >> obj.qt_installer_updater_icon_path - >> obj.qt_installer_online_repo >> obj.qt_installer_start_menue_link >> obj.qt_installer_desktop_link - >> obj.qt_installer_gpl3_licence >> obj.qt_m_updater_lib >> obj.qt_remove_shadow_build_setting - >> obj.qt_move_files_to_src_sub_dir >> obj.qt_app_icon >> obj.qt_installer_start_after_install - >> obj.qt_app_icon_path >> obj.git_init >> obj.git_enable_daily_auto_commit >> obj.git_init_readme - >> obj.git_add_git_ignore >> obj.git_set_remote_repo >> obj.remote_repo_url >> obj.qt_installer - >> obj.readme_init_text >> obj.git_overwriteReadmeFile >> obj.git_lfs >> obj.qt_installer_versionFile; - //Backwards Compatibility - } else if(obj.data_version == "1.3.0") { - - qDebug() << "Convert Data from 1.3.0"; - - in >> obj.magicNumber; - // Hier deserialisieren Sie alle zusätzlichen Datenmember - in >> obj.name >> obj.path >> obj.id - >> obj.qt_installer_name >> obj.qt_installer_version >> obj.qt_installer_titel - >> obj.qt_installer_publisher >> obj.qt_installer_start_menue_dir >> obj.qt_installer_online_repo_url - >> obj.qt_installer_package_name >> obj.qt_installer_description >> obj.qt_installer_updater_icon_path - >> obj.qt_installer_online_repo >> obj.qt_installer_start_menue_link >> obj.qt_installer_desktop_link - >> obj.qt_installer_gpl3_licence >> obj.qt_m_updater_lib >> obj.qt_remove_shadow_build_setting - >> obj.qt_move_files_to_src_sub_dir >> obj.qt_app_icon >> obj.qt_installer_start_after_install - >> obj.qt_app_icon_path >> obj.git_init >> obj.git_enable_daily_auto_commit >> obj.git_init_readme - >> obj.git_add_git_ignore >> obj.git_set_remote_repo >> obj.remote_repo_url >> obj.qt_installer - >> obj.readme_init_text >> obj.git_overwriteReadmeFile >> obj.qt_installer_versionFile; - - obj.git_overwriteReadmeFile = false; // init new values! - - } else if(obj.data_version == "-1.0.0") { - - } else if(obj.data_version == "-1.0.0") { - - } else { - in >> obj.magicNumber; - obj.magicNumber = -1; - } - - - return in; - } bool dataValid() const; - QString getProjectDirPath(); + QString getProjectDirPath() const; QString getExePath(); QString getAppName(); QString getAppVersion(); @@ -110,7 +56,11 @@ public: static size_t countComments(ProjektData *data); static QList countCommitsByDate(ProjektData *data); + // Convert paths to portable format + QString toPortablePath(const QString& absolutePath) const; + // Convert paths from portable format to absolute + QString toAbsolutePath(const QString& portablePath) const; QString getName() const { return name; } QString getPath() const { return path; } @@ -162,6 +112,11 @@ public: bool getGit_lfs() const; private: + // Helper method to write project data to a QDataStream + void writeToStream(QDataStream &out) const; + + // Helper method to read project data from a QDataStream + static ProjektData* readFromStream(QDataStream &in, const QString& projectDir); size_t magicNumber = -1; static constexpr size_t MAGIC_NUM = 1225356987344; @@ -219,54 +174,29 @@ class ProjektDataList : public QList public: ~ProjektDataList(); - friend QDataStream& operator<<(QDataStream& out, const ProjektDataList& list) { - //Version - out << DATA_VERSION; - - //Data - for (const ProjektData* data : list) { - out << *data; // Serialize each ProjektData object in the list - } - return out; - } - - friend QDataStream& operator>>(QDataStream& in, ProjektDataList& list) { - // Clear the list before reading new data - list.clear(); - - //Version - in >> list.dataVersion; - - if(list.dataVersion != DATA_VERSION) { - //Create BackUp - qDebug() << "list.dataVersion != DATA_VERSION ==> Create BackUP!"; - list.store(list.settingsPath + "_Backup"); - } - - // Read each ProjektData object and add it to the list - while (!in.atEnd()) { - ProjektData* data = new ProjektData(list.dataVersion); - in >> *data; - list.append(data); - } - return in; - } - - ProjektDataList(QString settingsPath); + // Constructor with company and application names for QSettings + ProjektDataList(const QString& company, const QString& appName); + // Save the list of project paths to QSettings bool store(); - bool store(QString path); - + // Load projects from paths stored in QSettings bool load(); - bool load(QString path); + // Add a project to the list and save its path to QSettings + void addProject(ProjektData* project); + + // Remove a project from the list and QSettings + bool removeProject(ProjektData* project); + bool removeProject(size_t id); + bool removeProject(int index); + + // Replace a project in the list + bool replaceProject(int index, ProjektData* newProject); private: - QString settingsPath; - QString dataVersion = DATA_VERSION; - + QString company; + QString appName; }; - #endif // PROJEKTDATA_H