diff --git a/25_folder.png b/25_folder.png new file mode 100644 index 0000000..d54f034 Binary files /dev/null and b/25_folder.png differ diff --git a/Icons.qrc b/Icons.qrc new file mode 100644 index 0000000..837df5a --- /dev/null +++ b/Icons.qrc @@ -0,0 +1,22 @@ + + + block.png + cupboard.png + download.png + gear.png + gears.png + lock.png + magnifier.png + refresh.png + tick.png + advanced_directory.png + file.png + filetype_pdf.png + filetype_rar.png + filetype_zip.png + 25_folder.png + library.png + library_32x32.ico + drive.png + + diff --git a/Sync-my-L2P.icns b/Sync-my-L2P.icns new file mode 100644 index 0000000..ce50909 Binary files /dev/null and b/Sync-my-L2P.icns differ diff --git a/Sync-my-L2P.pro b/Sync-my-L2P.pro new file mode 100644 index 0000000..fd27df9 --- /dev/null +++ b/Sync-my-L2P.pro @@ -0,0 +1,89 @@ +QT += gui core network +SOURCES += \ + main.cpp \ + hauptfenster.cpp \ + strukturelement.cpp \ + datei.cpp \ + logintester.cpp \ + dateidownloader.cpp \ + mysortfilterproxymodel.cpp + +HEADERS += \ + hauptfenster.h \ + strukturelement.h \ + datei.h \ + logintester.h \ + dateidownloader.h \ + mysortfilterproxymodel.h + +FORMS += \ + hauptfenster.ui \ + logintester.ui \ + dateidownloader.ui \ + syncfinisheddialog.ui + +RESOURCES += \ + Icons.qrc + +RC_FILE += \ + ../Sync-my-L2P/icon.rc + +ICON = Sync-my-L2P.icns + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/advanced_directory.png b/advanced_directory.png new file mode 100644 index 0000000..c2716bd Binary files /dev/null and b/advanced_directory.png differ diff --git a/block.png b/block.png new file mode 100644 index 0000000..b381adc Binary files /dev/null and b/block.png differ diff --git a/cupboard.png b/cupboard.png new file mode 100644 index 0000000..2591601 Binary files /dev/null and b/cupboard.png differ diff --git a/datei.cpp b/datei.cpp new file mode 100644 index 0000000..ecf9250 --- /dev/null +++ b/datei.cpp @@ -0,0 +1,24 @@ +#include "datei.h" + +Datei::Datei(QString name, QUrl url, QDateTime zeit, qint32 groesse) + :Strukturelement(name, url, fileItem), zeit(zeit) +{ + this->size = groesse; +} + +Datei::Datei(QString name, QUrl url, QString zeit, qint32 groesse) + : Strukturelement(name, url, fileItem), zeit(QDateTime::fromString(zeit, Qt::ISODate)) +{ + this->size = groesse; +} + +QDateTime Datei::GetZeit() const +{ + return zeit; +} + + +qint32 Datei::getSize() const +{ + return size; +} diff --git a/datei.h b/datei.h new file mode 100644 index 0000000..4baa485 --- /dev/null +++ b/datei.h @@ -0,0 +1,18 @@ +#ifndef DATEI_H +#define DATEI_H +#include + + +class Datei : public Strukturelement +{ +public: + Datei(QString name, QUrl url, QDateTime zeit, qint32 size); + Datei(QString name, QUrl url, QString zeit, qint32 size); + QDateTime GetZeit() const; + qint32 getSize() const; + +private: + QDateTime zeit; +}; + +#endif // DATEI_H diff --git a/dateidownloader.cpp b/dateidownloader.cpp new file mode 100644 index 0000000..572358e --- /dev/null +++ b/dateidownloader.cpp @@ -0,0 +1,133 @@ +#include "dateidownloader.h" +#include "ui_dateidownloader.h" + +DateiDownloader::DateiDownloader(QString benutzername, + QString passwort, + int anzahlItems, + QWidget *parent) : + QDialog(parent, Qt::FramelessWindowHint), + ui(new Ui::DateiDownloader), + benutzername(benutzername), + passwort(passwort), + anzahlItems(anzahlItems) +{ + ui->setupUi(this); + manager = new QNetworkAccessManager(this); + + QObject::connect(manager, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)) + , this, SLOT(authenticate(QNetworkReply*, QAuthenticator*))); + this->show(); + + // Zentrieren des Fensters + QRect desktopRect = parentWidget()->frameGeometry(); + QRect windowRect = this->frameGeometry(); + move((desktopRect.width()-windowRect.width())/2+desktopRect.x(), (desktopRect.height()-windowRect.height())/2+desktopRect.y()); +} + +DateiDownloader::~DateiDownloader() +{ + delete ui; +} + +void DateiDownloader::authenticate(QNetworkReply* , QAuthenticator* authenticator) +{ + authenticator->setUser(benutzername); + authenticator->setPassword(passwort); +} + +int DateiDownloader::startNextDownload(QString dateiname, QString veranstaltung, QString verzeichnisPfad, QUrl url, int itemNummer) +{ + // Anpassen der Labels + ui->progressLabel->setText(QString("Datei %1/%2").arg(itemNummer).arg(anzahlItems)); + ui->veranstaltungLabel->setText(veranstaltung); + ui->dateinameLabel->setText(dateiname); + + // Erstellen des Outputstreams + output.setFileName(verzeichnisPfad); + + // Öffnen des Outputstreams + if(!output.open(QIODevice::WriteOnly)) + { + QMessageBox messageBox; + messageBox.setText("Fehler beim Öffnen mit Schreibberechtigung."); + messageBox.setInformativeText(dateiname); + messageBox.setStandardButtons(QMessageBox::Ok); + messageBox.exec(); + return 0; + } + + // Start des Requests + reply = manager->get(QNetworkRequest(url)); + QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloadProgressSlot(qint64,qint64))); + QObject::connect(reply, SIGNAL(readyRead()), this, SLOT(readyReadSlot())); + QObject::connect(reply, SIGNAL(finished()), this, SLOT(finishedSlot())); + + // Schleife, die läuft, bis der Download abgeschlossen ist + return(loop.exec()); +} + +void DateiDownloader::downloadProgressSlot(qint64 bytesReceived, qint64 bytesTotal) +{ + if(bytesTotal) + { + ui->progressBar->setMaximum(bytesTotal); + ui->progressBar->setValue(bytesReceived); + + } + else + { + ui->progressBar->setMaximum(0); + ui->progressBar->setValue(0); + } +} + +void DateiDownloader::readyReadSlot() +{ + if (output.write(reply->readAll()) == -1) + { + QMessageBox messageBox; + messageBox.setText("Beim Schreiben einer Datei auf die Fesplatte ist ein Fehler aufgetreten."); + messageBox.setInformativeText(ui->dateinameLabel->text()); + messageBox.setStandardButtons(QMessageBox::Ok); + messageBox.exec(); + reply->abort(); + } +} + +void DateiDownloader::finishedSlot() +{ + output.flush(); + output.close(); + + QObject::disconnect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloadProgressSlot(qint64,qint64))); + QObject::disconnect(reply, SIGNAL(readyRead()), this, SLOT(readyReadSlot())); + QObject::disconnect(reply, SIGNAL(finished()), this, SLOT(finishedSlot())); + + reply->deleteLater(); + + if(reply->error()) + { + QMessageBox messageBox; + messageBox.setText("Beim Download einer Datei ist ein Fehler aufgetreten."); + messageBox.setInformativeText(ui->dateinameLabel->text()); + messageBox.setDetailedText(reply->errorString()); + messageBox.setStandardButtons(QMessageBox::Ok); + messageBox.exec(); + output.remove(); + loop.exit(0); + } + else + loop.exit(1); +} + +void DateiDownloader::keyPressEvent(QKeyEvent *event) +{ + if(event->key() == Qt::Key_Escape) + { + event->accept(); + reply->abort(); + } + else + event->ignore(); +} + diff --git a/dateidownloader.h b/dateidownloader.h new file mode 100644 index 0000000..70d3087 --- /dev/null +++ b/dateidownloader.h @@ -0,0 +1,56 @@ +#ifndef DATEIDOWNLOADER_H +#define DATEIDOWNLOADER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Ui { + class DateiDownloader; +} + +class DateiDownloader : public QDialog +{ + Q_OBJECT + +public: + explicit DateiDownloader(QString benutzername, + QString passwort, + int anzahlItems, + QWidget *parent= 0); + ~DateiDownloader(); + int startNextDownload(QString, QString, QString, QUrl, int); + +private: + + void keyPressEvent(QKeyEvent *); + Ui::DateiDownloader *ui; + QNetworkAccessManager* manager; + QNetworkReply* reply; + + QEventLoop loop; + + QString benutzername; + QString passwort; + + int anzahlItems; + + QFile output; + +private slots: + void authenticate(QNetworkReply*, QAuthenticator*); + void downloadProgressSlot(qint64,qint64); + void readyReadSlot(); + void finishedSlot(); +}; + +#endif // DATEIDOWNLOADER_H diff --git a/dateidownloader.ui b/dateidownloader.ui new file mode 100644 index 0000000..10ba469 --- /dev/null +++ b/dateidownloader.ui @@ -0,0 +1,266 @@ + + + DateiDownloader + + + + 0 + 0 + 680 + 180 + + + + + 0 + 0 + + + + + 680 + 180 + + + + + 680 + 180 + + + + Qt::NoContextMenu + + + + + + true + + + + + 10 + 110 + 660 + 60 + + + + + 0 + 0 + + + + + 660 + 60 + + + + + 660 + 60 + + + + Qt::NoContextMenu + + + + + + 0 + + + 0 + + + -1 + + + Qt::AlignCenter + + + true + + + Qt::Horizontal + + + false + + + QProgressBar::TopToBottom + + + %v/%m Byte + + + + + + 10 + 10 + 660 + 30 + + + + + 0 + 0 + + + + + 660 + 30 + + + + + 660 + 30 + + + + + 12 + 75 + true + + + + Qt::NoContextMenu + + + font: bold 12pt; + + + QFrame::NoFrame + + + QFrame::Plain + + + Download Datei 12/54 + + + Qt::AlignCenter + + + Qt::NoTextInteraction + + + + + + 10 + 40 + 660 + 30 + + + + + 0 + 0 + + + + + 660 + 30 + + + + + 660 + 30 + + + + + 11 + 50 + false + + + + Qt::NoContextMenu + + + QFrame::NoFrame + + + QFrame::Plain + + + Grundgebiete der Dödel + + + Qt::AlignCenter + + + Qt::NoTextInteraction + + + + + + 10 + 60 + 660 + 30 + + + + + 0 + 0 + + + + + 660 + 30 + + + + + 660 + 30 + + + + + 10 + 50 + false + + + + Qt::NoContextMenu + + + QFrame::NoFrame + + + QFrame::Plain + + + Datei.pdf + + + Qt::AlignCenter + + + Qt::NoTextInteraction + + + + + + diff --git a/download.png b/download.png new file mode 100644 index 0000000..291bf01 Binary files /dev/null and b/download.png differ diff --git a/drive.png b/drive.png new file mode 100644 index 0000000..d96f935 Binary files /dev/null and b/drive.png differ diff --git a/file.png b/file.png new file mode 100644 index 0000000..7514b22 Binary files /dev/null and b/file.png differ diff --git a/filetype_pdf.png b/filetype_pdf.png new file mode 100644 index 0000000..43a8d48 Binary files /dev/null and b/filetype_pdf.png differ diff --git a/filetype_rar.png b/filetype_rar.png new file mode 100644 index 0000000..4c1b2e0 Binary files /dev/null and b/filetype_rar.png differ diff --git a/filetype_zip.png b/filetype_zip.png new file mode 100644 index 0000000..ad5db13 Binary files /dev/null and b/filetype_zip.png differ diff --git a/gear.png b/gear.png new file mode 100644 index 0000000..af73abd Binary files /dev/null and b/gear.png differ diff --git a/gears.png b/gears.png new file mode 100644 index 0000000..90922e3 Binary files /dev/null and b/gears.png differ diff --git a/hauptfenster.cpp b/hauptfenster.cpp new file mode 100644 index 0000000..0dd5d96 --- /dev/null +++ b/hauptfenster.cpp @@ -0,0 +1,973 @@ +#include "hauptfenster.h" +#include "ui_hauptfenster.h" + +// Hauptadresse des Sharepointdienstes +QString StammURL = "https://www2.elearning.rwth-aachen.de"; + +Hauptfenster::Hauptfenster(QWidget *parent) : + QMainWindow(parent, Qt::CustomizeWindowHint|Qt::WindowTitleHint|Qt::WindowCloseButtonHint + | Qt::WindowMinimizeButtonHint), + ui(new Ui::Hauptfenster) +{ + ui->setupUi(this); + + // Laden von gespeicherten Einstellungen + QSettings einstellungen("Robert K.", "L2P-Tool++"); + + // Laden der Logindaten + if (einstellungen.value("login/save").toBool()) + { + ui->BenutzernameFeld->setText(einstellungen.value("login/benutzername","").toString()); + ui->PasswortFeld->setText(einstellungen.value("login/passwort","").toString()); + ui->DatenSpeichern->setChecked(true); + ui->AutoLogin->setEnabled(false); + } + + // Laden des Downloadverzeichnisses + ui->VerzeichnisFeld->setText(einstellungen.value("verzeichnis","").toString()); + if(!ui->VerzeichnisFeld->text().isEmpty()) + ui->directoryOpen->setEnabled(true); + + // Laden der gesetzten Filter und sonstigen Einstellungen + ui->autoSyncCheck->setChecked(einstellungen.value("autoSync").toBool()); + ui->documentsCheck->setChecked(einstellungen.value("documents").toBool()); + ui->structeredDocumentsCheck->setChecked(einstellungen.value("structuredDocuments").toBool()); + ui->exercisesCheck->setChecked(einstellungen.value("exercises").toBool()); + ui->maxSizeCheckBox->setChecked(einstellungen.value("maxSizeCB").toBool()); + ui->maxSizeBox->setValue(einstellungen.value("maxSizeB").toInt()); + + // Variable für das automatische Synchronisieren beim Programmstart + autoSynchronize = false; + + // Erzeugen des NetzwerkAccessManagers + manager = new QNetworkAccessManager(qApp); + QObject::connect(manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)) + ,this, SLOT(authentifizieren(QNetworkReply*, QAuthenticator*))); + + // Hinzufügen der Daten zur Baumansicht + proxymodel.setDynamicSortFilter(true); + proxymodel.setSourceModel(&veranstaltungen); + ui->treeView->setModel(&proxymodel); + //ui->treeView->setModel(&veranstaltungen); + + // Starten der Darstellung des Fensters + this->show(); + + // Zentrieren des Fensters + QRect desktopRect = QApplication::desktop()->screenGeometry(); + QRect windowRect = this->frameGeometry(); + move((desktopRect.width()-windowRect.width())/2, (desktopRect.height()-windowRect.height())/2); + + // Ausführen des Autologins, falls gewünscht + if (einstellungen.value("login/autoLogin").toBool()) + { + autoSynchronize = ui->autoSyncCheck->isChecked(); + on_Login_clicked(); + } +} + +Hauptfenster::~Hauptfenster() +{ + // Speichern aller Einstellungen + QSettings einstellungen("Robert K.", "L2P-Tool++"); + einstellungen.setValue("login/save", ui->DatenSpeichern->isChecked()); + if (ui->DatenSpeichern->isChecked()) + { + einstellungen.setValue("login/benutzername", ui->BenutzernameFeld->text()); + einstellungen.setValue("login/passwort", ui->PasswortFeld->text()); + einstellungen.setValue("login/autoLogin", ui->AutoLogin->isChecked()); + } + else + { + einstellungen.remove("login"); + } + einstellungen.setValue("verzeichnis", ui->VerzeichnisFeld->text()); + einstellungen.setValue("autoSync", ui->autoSyncCheck->isChecked()); + einstellungen.setValue("documents", ui->documentsCheck->isChecked()); + einstellungen.setValue("structuredDocuments", ui->structeredDocumentsCheck->isChecked()); + einstellungen.setValue("exercises", ui->exercisesCheck->isChecked()); + einstellungen.setValue("maxSizeCB", ui->maxSizeCheckBox->isChecked()); + einstellungen.setValue("maxSizeB", ui->maxSizeBox->value()); + delete ui; +} + +void Hauptfenster::on_Aktualisieren_clicked() +{ + // Löschen der alten Veranstaltungsliste + veranstaltungen.clear(); + + // Zurücksetzen der freigeschalteten Schaltflächen + ui->Aktualisieren-> setEnabled(false); + ui->ausschliessen-> setEnabled(false); + ui->einbinden-> setEnabled(false); + ui->synchronisieren-> setEnabled(false); + + // Einfrieren der Anzeige + ui->centralwidget-> setEnabled(false); + + // Verbinden des Managers + QObject::connect(manager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(veranstaltungenAbgerufen(QNetworkReply*))); + + // Starten der Anfrage + replies.insert(manager->get(QNetworkRequest(QUrl(StammURL % "/foyer/summary/default.aspx"))), 0); + + // Starten einer zweiten Anfrage für ältere Semester, falls eingestellt + if(ui->alteSemesterCheck->isChecked()) + replies.insert(manager->get(QNetworkRequest(QUrl(StammURL % "/foyer/archive/default.aspx"))), 0); +} + +void Hauptfenster::veranstaltungenAbgerufen(QNetworkReply* reply) +{ + // Prüfen auf Fehler beim Abruf + if(!reply->error()) + { + // Auslesen der kompletten Antwort + QString replyText = reply->readAll(); + + // Erstellen eines RegExps für das Herausfiltern der Veranstaltungen + QString regPattern = "(.{,150})indexIn(replyText, altePosition)) != -1) + { + // Anpassen der Encodierung wegen der Umlaute + urlRaum = QString::fromUtf8(regExp->cap(1).toLatin1()); + veranstaltungName = QString::fromUtf8(regExp->cap(2).toLatin1()); + veranstaltungName.replace(*escapeRegExp, ""); + + + // Erstellen der neuen Veranstaltung + neueVeranstaltung = new Strukturelement(veranstaltungName, QUrl(StammURL % urlRaum), courseItem);// % "/materials/documents/")); + //neueVeranstaltung = new Strukturelement(veranstaltungName, QUrl(StammURL % urlRaum % "/materials/structured/")); + neueVeranstaltung->setIcon(QIcon(":/icons/directory")); + + // Hinzufügen der Veranstaltung zur Liste + veranstaltungen.appendRow(neueVeranstaltung); + + // Weitersetzen der Suchposition hinter den letzten Fund + altePosition = neuePosition + regExp->matchedLength(); + } + + + + // Löschen der RegExps aus dem Speicher + delete regExp; + delete escapeRegExp; + } + else + { + // Falls ein Fehler aufgetreten sein sollte, Ausgabe dessen + QMessageBox messageBox; + messageBox.setText("Beim Abruf der Veranstaltungen ist ein Fehler aufgetreten"); + messageBox.setInformativeText(reply->errorString()); + messageBox.setStandardButtons(QMessageBox::Ok); + messageBox.exec(); + autoSynchronize = false; + } + + // Löschen der Antwort aus der Queue + replies.remove(reply); + + // Löschen der Antwort aus dem Speicher + reply->deleteLater(); + + // Prüfen, ob noch Antworten ausstehen und ggf. Reaktiveren der Benutzeroberfläche + if (replies.isEmpty()) + { + // Veranstaltungen alphabetisch sortieren + veranstaltungen.sort(0); + + QObject::disconnect(manager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(veranstaltungenAbgerufen(QNetworkReply*))); + + // Aufruf der Funktion zur Aktualisierung der Dateien + dateienAktualisieren(); + } +} + +void Hauptfenster::dateienAktualisieren() +{ + // Prüfen, ob überhaupt Dokumentorte ausgewählt wurden + if (!ui->documentsCheck->isChecked() && !ui->structeredDocumentsCheck->isChecked() && !ui->exercisesCheck->isChecked()) + { + // Freischalten von Schaltflächen + ui->Aktualisieren->setEnabled(true); + ui->centralwidget->setEnabled(true); + autoSynchronize = false; + return; + } + + QObject::connect(manager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(dateienAbgerufen(QNetworkReply*))); + + // Durchlaufen aller Veranstaltungen + int rowCount = veranstaltungen.rowCount(); + Strukturelement* aktuelleStruktur = 0; + + // Übungsbetrieb Lösungen + // "https://www2.elearning.rwth-aachen.de/ws10/10ws-02568/exerciseCourse/SampleSolutions/" + + // Übungsbetrieb Blätter + // "https://www2.elearning.rwth-aachen.de/ss11/11ss-33668/exerciseCourse/AssignmentDocuments/ + + for(int i= 0; i < rowCount; i++) + { + // Holen der aktuellen Veranstaltung + aktuelleStruktur = (Strukturelement*) veranstaltungen.item(i); + + // Löschen aller Dateien + if(aktuelleStruktur->rowCount() > 0) + aktuelleStruktur->removeRows(0, aktuelleStruktur->rowCount()); + + // Ausführen des Requests für "Dokumente" + if (ui->documentsCheck->isChecked()) + { + // Erstellen eines WebDav Requests + QNetworkRequest request(QUrl(aktuelleStruktur->data(urlRole).toUrl().toString() % "/materials/documents/")); + request.setRawHeader("Depth", "infinity"); + request.setRawHeader("Content-Type", "text/xml; charset=\"utf-8\""); + request.setRawHeader("Content-Length", "xxxx"); + + // Einfügen und Absenden des Requests + replies.insert(manager->sendCustomRequest(request, "PROPFIND"), aktuelleStruktur); + } + + // Ausführen des Requests für "Strukturierte Materialien" + if (ui->structeredDocumentsCheck->isChecked()) + { + // Erstellen eines WebDav Requests + QNetworkRequest request2(QUrl(aktuelleStruktur->data(urlRole).toUrl().toString() % "/materials/structured/")); + request2.setRawHeader("Depth", "infinity"); + request2.setRawHeader("Content-Type", "text/xml; charset=\"utf-8\""); + request2.setRawHeader("Content-Length", "xxxx"); + + // Einfügen in die Map und Absenden des Requests + replies.insert(manager->sendCustomRequest(request2, "PROPFIND"), aktuelleStruktur); + } + + if (ui->exercisesCheck->isChecked()) + { + // Erstellen eines WebDav Requests + QNetworkRequest request(QUrl(aktuelleStruktur->data(urlRole).toUrl().toString() % "/exerciseCourse/SampleSolutions/")); + request.setRawHeader("Depth", "infinity"); + request.setRawHeader("Content-Type", "text/xml; charset=\"utf-8\""); + request.setRawHeader("Content-Length", "xxxx"); + + // Einfügen und Absenden des Requests + replies.insert(manager->sendCustomRequest(request, "PROPFIND"), aktuelleStruktur); + + // Erstellen eines WebDav Requests + QNetworkRequest request2(QUrl(aktuelleStruktur->data(urlRole).toUrl().toString() % "/exerciseCourse/AssignmentDocuments/")); + request2.setRawHeader("Depth", "infinity"); + request2.setRawHeader("Content-Type", "text/xml; charset=\"utf-8\""); + request2.setRawHeader("Content-Length", "xxxx"); + + // Einfügen und Absenden des Requests + replies.insert(manager->sendCustomRequest(request2, "PROPFIND"), aktuelleStruktur); + } + } + + // Sonderfall: Es existieren keine Veranstaltungen + if (rowCount == 0) + { + QObject::disconnect(manager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(dateienAbgerufen(QNetworkReply*))); + + // Freischalten von Schaltflächen + ui->Aktualisieren-> setEnabled(true); + ui->einbinden-> setEnabled(true); + ui->ausschliessen-> setEnabled(true); + ui->synchronisieren->setEnabled(true); + ui->centralwidget-> setEnabled(true); + + autoSynchronize = false; + } +} + +void Hauptfenster::dateienAbgerufen(QNetworkReply* reply) +{ + // Prüfen auf Fehler + if (!reply->error()) + { + // Holen die aktuelle Veranstaltung aus der Map + Strukturelement* aktuellerOrdner = replies.value(reply); + + // Auslesen der Antwort und Speichern in dem XmlReader + QString replyText = reply->readAll(); + QXmlStreamReader Reader; + Reader.addData(replyText); + + // Vorbereitung der Daten für die Elemente + QString currentTag; + QUrl url; + QString name; + QString zeit; + qint32 size = 0; + + // Prüfen auf das Ende + while(!Reader.atEnd()) + { + // Lese nächstes Element + Reader.readNext(); + + // 1. Fall: Öffnendes Element + if(Reader.isStartElement()) + { + // Speichern des Namens + currentTag = Reader.name().toString(); + } + + // 2. Fall: Schließendes Element mit Namen Response + else if (Reader.isEndElement() && Reader.name() == "response") + { + // Hinzufügen des Slashs bei der Url von Ordnern + if(!size) + url.setUrl(url.toString() % "/"); + + // Wechsel in den übergeordneten Ordner des aktuellen Elements + while(!url.toString().contains((aktuellerOrdner->data(urlRole).toUrl().toString()), Qt::CaseSensitive))//(in = RegExp.indexIn(url.toString())) == -1) + { + aktuellerOrdner->sortChildren(0, Qt::AscendingOrder); + aktuellerOrdner = (Strukturelement*)aktuellerOrdner->parent(); + } + + // Ignorieren aller Adressen, die "/Forms" enthalten + if (!url.toString().contains("/Forms", Qt::CaseSensitive)) + { + // Prüfe auf Elementart + // 1. Fall: Datei (size > 0) + if (size) + { + // Erstellen einer neuen Datei + Datei* neueDatei = new Datei(name, url, zeit, size); + + // Hinzufügen des endungsabhängigen Icons + // PDF + if (name.contains(QRegExp(".pdf$", Qt::CaseInsensitive))) + neueDatei->setData(QIcon(":/icons/filetype_pdf.png"), Qt::DecorationRole); + + // ZIP + else if (name.contains(QRegExp(".zip$", Qt::CaseInsensitive))) + neueDatei->setData(QIcon(":/icons/filetype_zip.png"), Qt::DecorationRole); + + // RAR + else if (name.contains(QRegExp(".rar$", Qt::CaseInsensitive))) + neueDatei->setData(QIcon(":/icons/filetype_rar.png"), Qt::DecorationRole); + + // Sonstige + else + neueDatei->setData(QIcon(":/icons/file.png"), Qt::DecorationRole); + + // Hinzufügen zum aktuellen Ordner + aktuellerOrdner->appendRow(neueDatei); + } + // 2. Fall: Ordner/Veranstaltung + // Ausschließen der Ordnernamen "documents" und "structured" + else if (name != "documents" && name != "structured" && !url.toString().contains("exerciseCourse")) + { + // Erstellen eines neuen Ordners + Strukturelement* neuerOrdner = new Strukturelement(name, url, directoryItem); + + // Setzen des Zeichens + neuerOrdner->setData(QIcon(":/icons/25_folder.png"), Qt::DecorationRole); + + // Hinzufügen zum aktuellen Ordner + aktuellerOrdner->appendRow(neuerOrdner); + + // NeuerOrdner wird zum aktuellen Ordner + aktuellerOrdner = neuerOrdner; + } + } + + // Löschen aller eingelesener Daten + url.clear(); + name.clear(); + size = 0; + zeit.clear(); + } + + // Einlesen der Elementeigenschaften + else if (Reader.isCharacters() && !Reader.isWhitespace()) + { + // URL + if(currentTag == "href") + url.setUrl(QString::fromUtf8(Reader.text().toString().toLatin1())); + + // Name + else if (currentTag == "displayname") + name = QString::fromUtf8(Reader.text().toString().toLatin1()); + + // Größe + else if (currentTag == "getcontentlength") + size = Reader.text().toString().toInt(); + + // Modifizierungsdatum + else if (currentTag == "getlastmodified") + zeit = QString::fromUtf8(Reader.text().toString().toLatin1()); + } + } + + // Sortieren aller Dateien + aktuellerOrdner->sortChildren(0, Qt::AscendingOrder); + replies.value(reply)->sortChildren(0, Qt::AscendingOrder); + } + // Ausgabe einer Fehlermeldung bei Fehlern + // Ignoriere "ContentNotFoundError", der bei leeren Veranstaltungen auftritt + else if(reply->error() != QNetworkReply::ContentNotFoundError) + { + QMessageBox messageBox; + messageBox.setText("Beim Abruf des Inhalts einer Veranstaltung ist ein Fehler aufgetreten"); + messageBox.setInformativeText(reply->errorString()); + messageBox.setStandardButtons(QMessageBox::Ok); + messageBox.exec(); + } + + // Entfernen von leeren Veranstaltungen +// Strukturelement* aktuelleVeranstaltung = replies.value(reply); +// if(!aktuelleVeranstaltung->hasChildren()) +// { +// veranstaltungen.removeRow(veranstaltungen.indexFromItem(aktuelleVeranstaltung).row()); +// } + + // Löschen der Antwort aus der Liste der abzuarbeitenden Antworten + replies.remove(reply); + + // Freigabe des Speichers + reply->deleteLater(); + + // Prüfen, ob alle Antworten bearbeitet wurden -> Replies.empty() = TRUE + if(replies.empty()) + { + QObject::disconnect(manager, SIGNAL(finished(QNetworkReply*)), + this, SLOT(dateienAbgerufen(QNetworkReply*))); + + // Freischalten von Schaltflächen + ui->Aktualisieren-> setEnabled(true); + ui->einbinden-> setEnabled(true); + ui->ausschliessen-> setEnabled(true); + ui->synchronisieren->setEnabled(true); + ui->centralwidget-> setEnabled(true); + + // Falls bisher noch nicht synchronisiert wurde und Synchronisation beim Start aktiviert wurde + if (autoSynchronize) + { + autoSynchronize = false; + on_synchronisieren_clicked(); + } + + } +} + +void Hauptfenster::on_ausschliessen_clicked() +{ + // Holen der ausgewählten Dateien + QModelIndexList ausgewaehlt = proxymodel.mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); + + // Iteration über alle Elemente + Strukturelement* aktuelleStruktur = 0; + QModelIndexList::Iterator iteratorEnd = ausgewaehlt.end(); + for(QModelIndexList::Iterator iter = ausgewaehlt.begin(); iter != iteratorEnd; iter++) + { + // Holen des Vaterelements des ausgewählten Strukturelements + aktuelleStruktur = (Strukturelement*) iter->internalPointer(); + + // Ausschließen des ausgewählten Elements + Strukturelement* temp = (Strukturelement*)aktuelleStruktur->child(iter->row(),0); + ausschliessen(temp); + //ausschliessen((Strukturelement*)aktuelleStruktur->child(iter->row(),0)); + + // Prüfen, ob alle Geschwisterelemente ausgeschlossen sind + // => Ausschließen des Vaterlements + if(aktuelleStruktur != veranstaltungen.invisibleRootItem()) + { + bool siblingsExcluded = true; + + // Prüfung aller Zeilen, ob alle ausgeschlossen + for (int i=0; i < aktuelleStruktur->rowCount(); i++) + { + if(((Strukturelement*)aktuelleStruktur->child(i,0))->data(includeRole).toBool()) + siblingsExcluded = false; + } + + // Falls ja, Vaterelement auch ausschließen + if (siblingsExcluded) + { + aktuelleStruktur->setData(false, includeRole); + //aktuelleStruktur = (Strukturelement*) aktuelleStruktur->parent(); + } + else + { + } + } + } + + // Aktualisieren der Ansicht + ui->treeView->dataChanged(veranstaltungen.index(0,0),veranstaltungen.index(veranstaltungen.rowCount(),0)); +} + +void Hauptfenster::ausschliessen(Strukturelement* aktuelleStruktur) +{ + // Ausschließen aller untergeordneten Elemente + if(aktuelleStruktur->data(includeRole).toBool()){ + aktuelleStruktur->setData(false, includeRole); + for(int i = 0; i < aktuelleStruktur->rowCount(); i++) + { + ausschliessen((Strukturelement*)aktuelleStruktur->child(i,0)); + } + } +} + +void Hauptfenster::on_einbinden_clicked() +{ + // Bestimmen der ausgewählten Items + QModelIndexList selectedItemsList = proxymodel.mapSelectionToSource(ui->treeView->selectionModel()->selection()).indexes(); + + // Variablen zur Speicherung von Pointern aus Performancegründen vor der Schleife + Strukturelement* aktuelleStruktur = 0; + QModelIndexList::Iterator iteratorEnd = selectedItemsList.end(); + + for(QModelIndexList::Iterator iterator = selectedItemsList.begin(); iterator != iteratorEnd; iterator++) + { + // Holen des Pointers auf das ausgewählte Item + aktuelleStruktur = (Strukturelement*)((Strukturelement*) iterator->internalPointer())->child(iterator->row(),0); + + // Einbinden aller übergeordneter Ordner + Strukturelement* parent = aktuelleStruktur; + while((parent = (Strukturelement*) parent->parent()) != 0) + { + if (parent->data(includeRole).toBool()) + break; + parent->setData(true, includeRole); + } + + // Einbinden aller untergeordneter Ordner und Dateien + einbinden(aktuelleStruktur); + } + + // Aktualisierung der Ansicht + ui->treeView->dataChanged(veranstaltungen.index(0,0),veranstaltungen.index(veranstaltungen.rowCount(),0)); +} + +void Hauptfenster::einbinden(Strukturelement* aktuelleStruktur) +{ + // Einbinden des aktuellen Items + aktuelleStruktur->setData(true, includeRole); + + // Einbinden aller untergeordnete Ordner und Dateien + int rowCount = aktuelleStruktur->rowCount(); + for(int i = 0; i < rowCount; i++) + { + einbinden((Strukturelement*)aktuelleStruktur->child(i,0)); + } +} + +void Hauptfenster::on_Login_clicked() +{ + // Erstellen eines Logintesters + LoginTester* LoginTest = new LoginTester(ui->BenutzernameFeld->text(), ui->PasswortFeld->text(), 2, this); + + // Testen des Logins + // 1.Fall: Login erfolgreich + if(LoginTest->exec()) + { + // Ändern des Schreibrechts der LineEdits + ui->BenutzernameFeld->setReadOnly(true); + ui->PasswortFeld->setReadOnly(true); + + // Hinzufügen eines neuen Styles + ui->BenutzernameFeld->setStyleSheet("QLineEdit{background-color:#6CFF47; font: bold}"); + ui->PasswortFeld->setStyleSheet("QLineEdit{background-color:#6CFF47; font: bold}"); + + // Aktualisieren der Buttons + ui->Login->setEnabled(false); + ui->Aktualisieren->setEnabled(true); + ui->AutoLogin->setEnabled(true); + ui->DatenSpeichern->setEnabled(true); + + // Setzen des buttons je nach Einstellung + QSettings einstellungen("Robert K.", "L2P-Tool++"); +// ui->DatenSpeichern->setChecked(einstellungen.value("login/save").toBool()); + ui->AutoLogin->setChecked(einstellungen.value("login/autoLogin").toBool()); + ui->autoSyncCheck->setChecked(einstellungen.value("autoSync").toBool()); + + // Anzeigen des Erfolgs in der Statusbar + ui->statusBar->showMessage("Login erfolgreich!"); + + // Sofortiges Aktualisiern der Daten + on_Aktualisieren_clicked(); + } + // 2.Fall: Login fehlgeschlagen + else + { + autoSynchronize = false; + } + delete LoginTest; +} + +void Hauptfenster::on_DatenSpeichern_stateChanged(int checked) +{ + // (De-)Aktivierung der Autologin CB + if(checked) + ui->AutoLogin->setEnabled(true); + else + ui->AutoLogin->setEnabled(false); + + // Löschen des Hakens + ui->AutoLogin->setChecked(false); +} + +void Hauptfenster::on_AutoLogin_stateChanged(int checked) +{ + // (De-)Aktivierung der Autologin CB + if(checked) + ui->autoSyncCheck->setEnabled(true); + else + ui->autoSyncCheck->setEnabled(false); + + // Löschen des Hakens + ui->autoSyncCheck->setChecked(false); +} + +void Hauptfenster::on_BenutzernameFeld_textChanged(const QString &arg1) +{ + aktiviereLoginButton(); +} + +void Hauptfenster::on_PasswortFeld_textChanged(const QString &arg1) +{ + aktiviereLoginButton(); +} + +void Hauptfenster::aktiviereLoginButton() +{ + // Löschen der gespeicherten Einstellungen, da neue Benutzerdaten vorliegen + ui->AutoLogin->setChecked(false); + ui->DatenSpeichern->setChecked(false); + + + // Aktivieren des Loginbuttons, wenn beide Felder ausgefüllt sind + if(!ui->BenutzernameFeld->text().isEmpty() && !ui->PasswortFeld->text().isEmpty()) + { + ui->Login->setEnabled(true); + } + else + { + ui->Login->setEnabled(false); + } +} + +void Hauptfenster::on_synchronisieren_clicked() +{ + ui->centralwidget->setEnabled(false); + QString directoryPath = ui->VerzeichnisFeld->text(); + + // Falls noch kein Pfad angegeben wurde, abbrechen und FileDialog öffnen + if (directoryPath.isEmpty()) + { + ui->tabWidget->setCurrentIndex(1); + on_directoryButton_clicked(); + ui->centralwidget->setEnabled(true); + return; + } + // Deaktivieren des DialogButtons + ui->directoryButton->setEnabled(false); + + QDir verzeichnis(directoryPath); + + // Überprüfung, ob das angegebene Verzeichnis existiert, oder erstellt werden kann + if(!verzeichnis.exists() && !verzeichnis.mkpath(verzeichnis.path())) + { + ui->directoryButton->setEnabled(true); + ui->centralwidget->setEnabled(true); + return; + } + + // Hinzufügen aller eingebundenen Elemente einer Liste + QLinkedList liste; + for(int i=0; i < veranstaltungen.rowCount(); i++) + { + getStrukturelementeListe((Strukturelement*)veranstaltungen.item(i,0), liste, true); + } + + if(!liste.isEmpty()){ + + DateiDownloader* loader = new DateiDownloader(ui->BenutzernameFeld->text(), // Benutzername + ui->PasswortFeld->text(), // Passwort + getFileCount(liste), // Anzahl der zu runterladenen Dateien + this); + + // Iterieren über alle Elemente + Strukturelement* aktuellerOrdner = liste.first(); + int counter = getFileCount(liste); + int changedCounter = 0; + bool neueVeranstaltung = false; + QString veranstaltungName; + QList downloadedItems; + for(QLinkedList::iterator iterator = liste.begin(); + iterator != liste.end(); + iterator++) + { + if((**iterator).parent() != 0) + { + while(!(**iterator).data(urlRole).toUrl().toString().contains( + aktuellerOrdner->data(urlRole).toUrl().toString(), Qt::CaseSensitive)) + { + + aktuellerOrdner = (Strukturelement*) aktuellerOrdner->parent(); + verzeichnis.cdUp(); + } + } + else + { + verzeichnis.setPath(ui->VerzeichnisFeld->text()); + neueVeranstaltung = true; + } + // 1. Fall: Ordner + if((**iterator).getSize() == 0) + { + if(!verzeichnis.exists((**iterator).text())) + { + if (!verzeichnis.mkdir((**iterator).text())) + { + QMessageBox messageBox; + messageBox.setText("Beim Erstellen eines Ordners ist ein Fehler aufgetreten."); + messageBox.setInformativeText((**iterator).text()); + messageBox.setStandardButtons(QMessageBox::Ok); + messageBox.exec(); + break; + } + } + if (neueVeranstaltung) + { + veranstaltungName = (**iterator).text(); + neueVeranstaltung = false; + } + + aktuellerOrdner = *iterator; + verzeichnis.cd((**iterator).text()); + } + // 2. Fall: Datei + else + { + // Datei existiert noch nicht + //counter++; + if (!verzeichnis.exists((**iterator).text()) || + (QFileInfo(verzeichnis, (**iterator).text()).size() + != (*((Datei*)(*iterator))).getSize())) + { + if (!loader->startNextDownload((**iterator).text(), + veranstaltungName, + verzeichnis.absoluteFilePath((**iterator).text()), + (**iterator).data(urlRole).toUrl(), + changedCounter+1)) + break; + changedCounter++; + downloadedItems.append((**iterator).text()); + } + } + } + loader->close(); + + QString downloadedItemsString; + + QString nstring; + foreach(nstring, downloadedItems) + { + downloadedItemsString.append(nstring%"\n"); + } + + QMessageBox messageBox(this); + messageBox.setText("Synchronisation mit dem L2P der RWTH Aachen abgeschlossen."); + messageBox.setIcon(QMessageBox::NoIcon); + messageBox.setInformativeText(QString("Es wurden %1 von %2 eingebundenen Dateien synchronisiert.") + .arg(QString::number(changedCounter), QString::number(counter))); + messageBox.setDetailedText(downloadedItemsString); + messageBox.setStandardButtons(QMessageBox::Ok); + messageBox.exec(); + } + ui->directoryButton->setEnabled(true); + ui->centralwidget->setEnabled(true); + + +} + +void Hauptfenster::getStrukturelementeListe(Strukturelement* aktuellesElement, QLinkedList& liste, bool onlyIncluded) +{ + if(!onlyIncluded || (onlyIncluded && aktuellesElement->data(includeRole).toBool())) + { + if ((ui->maxSizeCheckBox->isChecked() && aktuellesElement->getSize() < (ui->maxSizeBox->value() * 1024 * 1024)) + || !ui->maxSizeCheckBox->isChecked()) + liste.append(aktuellesElement); + if(aktuellesElement->hasChildren()) + for (int i = 0; i < aktuellesElement->rowCount(); i++) + getStrukturelementeListe((Strukturelement*)aktuellesElement->child(i, 0), liste, onlyIncluded); + } +} + +int Hauptfenster::getFileCount(QLinkedList& liste) +{ + // Zählen aller Dateien einer Liste mit einer Größe > 0 + int fileCounter = 0; + for(QLinkedList::iterator iterator = liste.begin(); iterator != liste.end(); iterator++) + { + if ((**iterator).getSize()) + fileCounter++; + } + return fileCounter; +} + +void Hauptfenster::authentifizieren(QNetworkReply* reply, QAuthenticator* auth) +{ + auth->setUser(ui->BenutzernameFeld->text()); + auth->setPassword(ui->PasswortFeld->text()); +} + +void Hauptfenster::unknownError() +{ + +} + +void Hauptfenster::on_directoryButton_clicked() +{ + // Aufruf des Ordnerdialogs + QString newDirectory = QFileDialog::getExistingDirectory(this, + "Downloadverkzeichnis auswählen", + QDir::rootPath(), + QFileDialog::ShowDirsOnly| QFileDialog::DontResolveSymlinks); + if (!newDirectory.isEmpty()) + ui->VerzeichnisFeld->setText(newDirectory); + + // Aktualisierung des Zustands des Buttons "Speicherort öffnen" + if(!ui->VerzeichnisFeld->text().isEmpty()) + ui->directoryOpen->setEnabled(true); + else + ui->directoryOpen->setEnabled(false); +} + + +void Hauptfenster::on_directoryOpen_clicked() +{ + // Betriebssystem soll mit dem Standardprogramm den Pfad öffnen + QDesktopServices::openUrl(QUrl("file:///" % ui->VerzeichnisFeld->text(), QUrl::TolerantMode)); +} + +void Hauptfenster::on_expandButton_clicked() +{ + // Expandieren aller Zweige + ui->treeView->expandAll(); +} + +void Hauptfenster::on_collapseButton_clicked() +{ + // Reduktion aller Zweige + ui->treeView->collapseAll(); +} + +void Hauptfenster::on_treeView_doubleClicked(const QModelIndex &index) +{ + Strukturelement* element = (Strukturelement*) veranstaltungen.itemFromIndex(proxymodel.mapToSource(index)); + if(element->getSize()) + if(!QDesktopServices::openUrl(QUrl(getStrukturelementPfad(element), QUrl::TolerantMode))) + { + QDesktopServices::openUrl(element->data(urlRole).toUrl()); + } +} + +QString Hauptfenster::getStrukturelementPfad(Strukturelement* element) +{ + QString path; + path.append(element->text()); + Strukturelement* parent = element; + while ((parent = (Strukturelement*) parent->parent()) != 0) + path.push_front(parent->text()%"/"); + path.push_front("file:///" % ui->VerzeichnisFeld->text()%"/"); + return path; +} + +void Hauptfenster::on_treeView_customContextMenuRequested(const QPoint &pos) +{ + // Bestimmung des Elements, auf das geklickt wurde + Strukturelement* RightClickedItem = (Strukturelement*) veranstaltungen.itemFromIndex(proxymodel.mapToSource(ui->treeView->indexAt(pos))); + + // Überprüfung, ob überhaupt auf ein Element geklickt wurde (oder ins Leere) + if (RightClickedItem == 0) + return; + + // Speichern des geklickten Items + lastRightClickItem = RightClickedItem; + + + // Erstellen eines neuen Menus + QMenu newCustomContextMenu(this); + + // Öffnen der Veranstaltungsseite im L2P + if (RightClickedItem->type() == courseItem) + { + QAction* openCourseAction = new QAction("Veranstaltungsseite öffnen", this); + newCustomContextMenu.addAction(openCourseAction); + QObject::connect(openCourseAction, SIGNAL(triggered()), this, SLOT(openCourse())); + } + + // Öffnen der Datei + QAction* openAction = new QAction("Öffnen", this); + newCustomContextMenu.addAction(openAction); + QObject::connect(openAction, SIGNAL(triggered()), this, SLOT(openItem())); + + // Kopieren der URL + QAction* copyAction = new QAction("Link kopieren", this); + newCustomContextMenu.addAction(copyAction); + QObject::connect(copyAction, SIGNAL(triggered()), this, SLOT(copyURL())); + + // Anzeigen des Menus an der Mausposition + newCustomContextMenu.exec(ui->treeView->mapToGlobal(pos)); +} + +void Hauptfenster::openCourse() +{ + QDesktopServices::openUrl(lastRightClickItem->data(urlRole).toUrl()); +} + +void Hauptfenster::openItem() +{ + if(!QDesktopServices::openUrl(QUrl(getStrukturelementPfad(lastRightClickItem), QUrl::TolerantMode))) + { + QDesktopServices::openUrl(lastRightClickItem->data(urlRole).toUrl()); + } +} + +void Hauptfenster::copyURL() +{ + // Holen der Zwischenablage + QClipboard *clipboard = QApplication::clipboard(); + + // Kopieren in die Zwischenablage + clipboard->setText(lastRightClickItem->data(urlRole).toUrl().toString()); +} + + + + +void Hauptfenster::on_maxSizeBox_valueChanged(int arg1) +{ + proxymodel.setMaximumSize(arg1); +} + +void Hauptfenster::on_maxSizeCheckBox_toggled(bool checked) +{ + proxymodel.setMaximumSizeFilter(checked); +} diff --git a/hauptfenster.h b/hauptfenster.h new file mode 100644 index 0000000..88e89f1 --- /dev/null +++ b/hauptfenster.h @@ -0,0 +1,104 @@ +#ifndef HAUPTFENSTER_H +#define HAUPTFENSTER_H + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include "datei.h" + +#include "logintester.h" +#include "dateidownloader.h" +#include "mysortfilterproxymodel.h" + +class Veranstaltung; + +namespace Ui { + class Hauptfenster; +} + +class Hauptfenster : public QMainWindow +{ + Q_OBJECT + +public: + explicit Hauptfenster(QWidget *parent = 0); + ~Hauptfenster(); + +private: + void ausschliessen(Strukturelement*); + void einbinden(Strukturelement*); + void aktiviereLoginButton(void); + void getStrukturelementeListe(Strukturelement*, QLinkedList&, bool); + + QString getStrukturelementPfad(Strukturelement*); + int getFileCount(QLinkedList& liste); + Ui::Hauptfenster *ui; + QNetworkAccessManager* manager; + MySortFilterProxyModel proxymodel; + QStandardItemModel veranstaltungen; + Strukturelement* iter; + QFile output; + QMap replies; + void unknownError(); + + Strukturelement* lastRightClickItem; + + bool autoSynchronize; + +signals: + void downloadFortschritt(int); + +private slots: + void copyURL(); + void openItem(); + void openCourse(); + void veranstaltungenAbgerufen(QNetworkReply*); + void authentifizieren(QNetworkReply*, QAuthenticator*); + void dateienAbgerufen(QNetworkReply*); + void dateienAktualisieren(); + void on_ausschliessen_clicked(); + void on_einbinden_clicked(); + void on_Login_clicked(); + void on_DatenSpeichern_stateChanged(int arg1); + void on_BenutzernameFeld_textChanged(const QString &arg1); + void on_PasswortFeld_textChanged(const QString &arg1); + void on_synchronisieren_clicked(); + void on_directoryButton_clicked(); + void on_Aktualisieren_clicked(); + void on_directoryOpen_clicked(); + void on_expandButton_clicked(); + void on_collapseButton_clicked(); + void on_AutoLogin_stateChanged(int arg1); + void on_treeView_doubleClicked(const QModelIndex &index); + void on_treeView_customContextMenuRequested(const QPoint &pos); + void on_maxSizeBox_valueChanged(int arg1); + void on_maxSizeCheckBox_toggled(bool checked); +}; + +#endif // HAUPTFENSTER_H diff --git a/hauptfenster.ui b/hauptfenster.ui new file mode 100644 index 0000000..043abb3 --- /dev/null +++ b/hauptfenster.ui @@ -0,0 +1,667 @@ + + + Hauptfenster + + + + 0 + 0 + 698 + 480 + + + + + 900 + 16777215 + + + + Sync-my-L²P + + + + :/icons/magnifier.png:/icons/magnifier.png + + + + + + + + 0 + 0 + + + + 0 + + + + + :/icons/cupboard.png:/icons/cupboard.png + + + Dateibrowser + + + + + + + 0 + 0 + + + + true + + + Qt::CustomContextMenu + + + QAbstractItemView::NoEditTriggers + + + true + + + false + + + true + + + QAbstractItemView::ExtendedSelection + + + true + + + true + + + true + + + false + + + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + Ansicht + + + + + + false + + + Aktualiseren aller Veranstaltungen und Dateien + + + aktualisieren + + + + :/icons/refresh.png:/icons/refresh.png + + + + + + + Expandieren aller Veranstaltungen und Ordner + + + alle expandieren + + + + + + + Rduzieren aller Veranstaltungen und Ordner + + + alle reduzieren + + + + + + + false + + + + 0 + 0 + + + + Öffnen des ausgewählten Downloadverzeichnisses + + + Speicherort öffnen + + + + :/icons/drive:/icons/drive + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 20 + + + + + + + + + 0 + 0 + + + + Dateifilter + + + + + + Auswahl einer maximalen Dateigröße für runterzuladene Dateien + + + Max. Größe + + + + + + + false + + + Namensfilter + + + + + + + false + + + Datumsfilter + + + + + + + + 0 + 0 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + MB + + + 1 + + + 999 + + + + + + + + + + + 0 + 0 + + + + + 150 + 0 + + + + Synchronisation + + + + + + false + + + Ausschließen aller ausgewählten Dateien aus der Synchronisation + + + ausschließen + + + + :/icons/block.png:/icons/block.png + + + + + + + false + + + Einbinden aller ausgewählten Dateien aus der Synchronisation + + + einbinden + + + + :/icons/tick.png:/icons/tick.png + + + + + + + false + + + + 75 + true + + + + Starten der Synchronisation + + + synchronsieren + + + + :/icons/download.png:/icons/download.png + + + + + + + + + + + + + + 0 + 0 + + + + + :/icons/gear.png:/icons/gear.png + + + Einstellungen + + + + + + + 0 + 0 + + + + Login + + + + + + + 315 + 30 + + + + + 75 + true + + + + Qt::AlignCenter + + + Benutzername + + + + + + + + 315 + 30 + + + + + 75 + true + + + + QLineEdit::Password + + + 0 + + + Qt::AlignCenter + + + Passwort + + + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + false + + + + 0 + 0 + + + + Speichern der Logindaten auf dem Computer + + + Logindaten speichern + + + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Start des Einlogvorgangs + + + Login + + + + :/icons/lock.png:/icons/lock.png + + + + + + + + + + + 0 + 0 + + + + Downloadverzeichnis + + + + + + + 0 + 0 + + + + + 0 + 30 + + + + + 75 + true + + + + Qt::AlignCenter + + + true + + + Downloadverzeichnis + + + + + + + + 0 + 0 + + + + ... + + + + + + + + + + + 0 + 0 + + + + Optionen + + + + + + Einschließen von "Dokumente" in die Synchronisation + + + "Dokumente" durchsuchen + + + true + + + + + + + Einschließen von "Strukturiete Materialien" in die Synchronisation + + + "Strukturierte Materialien" durchsuchen + + + true + + + + + + + Einschließen von "Ãœbungen" in die Synchronisation + + + "Ãœbungen" durchsuchen + + + true + + + + + + + Durchsuchen der vergangen Semester + + + frühere Semester durchsuchen + + + + + + + false + + + + 0 + 0 + + + + Automatischer Loginversuch beim Programmstart + + + Login beim Programstart + + + + + + + false + + + Automatische Synchronisation beim Programmstart + + + Synchronisation beim Programmstart + + + + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 0 + 0 + + + + + + + + + + + + + + + + + diff --git a/hauptfenster.uiOLD b/hauptfenster.uiOLD new file mode 100644 index 0000000..90239e5 --- /dev/null +++ b/hauptfenster.uiOLD @@ -0,0 +1,1223 @@ + + + Hauptfenster + + + Qt::NonModal + + + + 0 + 0 + 700 + 470 + + + + + 0 + 0 + + + + + 700 + 470 + + + + + 700 + 470 + + + + + Verdana + 9 + 50 + false + false + + + + Qt::NoContextMenu + + + Sync-my-L²P + + + + :/icons/magnifier.png:/icons/magnifier.png + + + font: 9pt "Verdana"; + + + QMainWindow::AllowTabbedDocks|QMainWindow::AnimatedDocks + + + + + 0 + 0 + + + + + 700 + 450 + + + + + 700 + 450 + + + + + + + + + 10 + 10 + 680 + 430 + + + + + 0 + 0 + + + + + 680 + 430 + + + + + 680 + 430 + + + + Qt::NoContextMenu + + + 0 + + + + 15 + 15 + + + + true + + + + + 0 + 0 + + + + + 680 + 430 + + + + + 680 + 430 + + + + + + + + :/icons/cupboard.png:/icons/cupboard.png + + + Dateibrowser + + + + + 10 + 10 + 450 + 380 + + + + + 0 + 0 + + + + + 450 + 380 + + + + + 450 + 380 + + + + + Verdana + 9 + 50 + false + false + + + + Qt::NoContextMenu + + + Qt::LeftToRight + + + + + + QFrame::StyledPanel + + + Qt::ScrollBarAsNeeded + + + Qt::ScrollBarAsNeeded + + + QAbstractItemView::NoEditTriggers + + + false + + + true + + + QAbstractItemView::ExtendedSelection + + + QAbstractItemView::SelectItems + + + + 16 + 16 + + + + Qt::ElideMiddle + + + 20 + + + true + + + false + + + true + + + false + + + + + + 470 + 10 + 201 + 381 + + + + + + + true + + + + 0 + 0 + + + + + 195 + 0 + + + + + 195 + 16777215 + + + + Qt::NoContextMenu + + + + + + Ansicht + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + 6 + + + 9 + + + + + false + + + + 0 + 0 + + + + Qt::NoContextMenu + + + Qt::LeftToRight + + + + + + aktualisieren + + + + :/icons/refresh.png:/icons/refresh.png + + + + 16 + 16 + + + + + + + + true + + + + 0 + 0 + + + + Qt::NoContextMenu + + + Qt::LeftToRight + + + + + + alle erweitern + + + + + + + true + + + + 0 + 0 + + + + Qt::NoContextMenu + + + Qt::LeftToRight + + + + + + alle reduzieren + + + + + + + false + + + + 0 + 0 + + + + Qt::NoContextMenu + + + Qt::LeftToRight + + + + + + Speicherort öffnen + + + + :/icons/drive:/icons/drive + + + + 16 + 16 + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + + 195 + 0 + + + + + 195 + 16777215 + + + + Qt::NoContextMenu + + + + + + Synchronisierung + + + + 6 + + + 9 + + + + + false + + + + 0 + 0 + + + + Qt::NoContextMenu + + + ausschließen + + + + :/icons/block.png:/icons/block.png + + + + 16 + 16 + + + + + + + + false + + + + 0 + 0 + + + + Qt::NoContextMenu + + + einbinden + + + + :/icons/tick.png:/icons/tick.png + + + + 16 + 16 + + + + + + + + false + + + + 0 + 0 + + + + + 100 + 50 + + + + Qt::NoContextMenu + + + font:bold; + + + synchronisieren + + + + :/icons/download.png:/icons/download.png + + + + 22 + 22 + + + + + + + + + + + + + + 680 + 430 + + + + + 680 + 430 + + + + + :/icons/gears.png:/icons/gears.png + + + Einstellungen + + + + + 460 + 380 + 209 + 16 + + + + + 0 + 0 + + + + + Times New Roman + 11 + 50 + false + false + + + + font: 11pt "Times New Roman"; + + + programed by Robert Krajewski + + + Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing + + + + + + 10 + 10 + 657 + 362 + + + + + 6 + + + + + + 0 + 0 + + + + + 655 + 0 + + + + + 655 + 16777215 + + + + Login + + + + + + + + + + + 0 + 0 + + + + + 315 + 30 + + + + + 315 + 30 + + + + + Verdana + 9 + 75 + false + true + + + + Qt::NoContextMenu + + + false + + + font: bold + + + 50 + + + true + + + Qt::AlignCenter + + + Benutzername + + + + + + + + 0 + 0 + + + + + 310 + 30 + + + + + 310 + 30 + + + + + Verdana + 9 + 75 + false + true + + + + Qt::NoContextMenu + + + font: bold + + + Qt::ImhHiddenText|Qt::ImhNoAutoUppercase|Qt::ImhNoPredictiveText + + + 50 + + + true + + + QLineEdit::Password + + + Qt::AlignCenter + + + Passwort + + + + + + + + + + + false + + + + 0 + 0 + + + + Qt::NoContextMenu + + + font: bold; + + + Login + + + + :/icons/lock.png:/icons/lock.png + + + + 16 + 16 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + + 0 + 0 + + + + Qt::NoContextMenu + + + Benutzerdaten speichern + + + + + + + false + + + + 0 + 0 + + + + Qt::NoContextMenu + + + Auto-Login beim Programmstart + + + + + + + + + + + + + + true + + + + 0 + 0 + + + + + 655 + 0 + + + + + 655 + 16777215 + + + + Qt::NoContextMenu + + + Downloadverzeichnis + + + + + + + + true + + + + 0 + 0 + + + + + 605 + 30 + + + + + 605 + 30 + + + + + Verdana + 9 + 75 + false + true + + + + font: bold + + + + + + Qt::AlignCenter + + + true + + + Bitte ein gültiges Downloadverzeichnis auswählen + + + + + + + + 30 + 32 + + + + + 30 + 32 + + + + ... + + + QToolButton::InstantPopup + + + Qt::ToolButtonIconOnly + + + false + + + + + + + + + + + + + 0 + 0 + + + + + 655 + 0 + + + + + 655 + 16777215 + + + + Qt::NoContextMenu + + + Filter + + + + 6 + + + 3 + + + 9 + + + + + true + + + Qt::NoContextMenu + + + Dokumente durchsuchen + + + true + + + false + + + + + + + true + + + Qt::NoContextMenu + + + Strukturierte Dokumente durchsuchen + + + true + + + + + + + + + Qt::LeftToRight + + + Maximale Dateigröße (in MB) + + + true + + + + + + + + 0 + 0 + + + + + 70 + 0 + + + + + 70 + 16777215 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 1 + + + 9999 + + + 50 + + + + + + + + + true + + + Qt::NoContextMenu + + + Ãœbungsbetrieb durchsuchen + + + true + + + false + + + + + + + + + + + 0 + 0 + + + + + 655 + 0 + + + + + 655 + 16777215 + + + + Qt::NoContextMenu + + + Sonstiges + + + + 6 + + + 9 + + + + + true + + + Qt::NoContextMenu + + + Alte Semester durchsuchen + + + + + + + true + + + Qt::NoContextMenu + + + Synchronisation beim Programmstart + + + + + + + + + + + + + + false + + + + + + + + + + 10 + + + 10 + + + true + + + true + + + true + + + diff --git a/icon.rc b/icon.rc new file mode 100644 index 0000000..2dbe2e3 --- /dev/null +++ b/icon.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "magnifier.ico" diff --git a/library.png b/library.png new file mode 100644 index 0000000..0db7c03 Binary files /dev/null and b/library.png differ diff --git a/library_32x32.ico b/library_32x32.ico new file mode 100644 index 0000000..62bdbbb Binary files /dev/null and b/library_32x32.ico differ diff --git a/lock.png b/lock.png new file mode 100644 index 0000000..ec9527a Binary files /dev/null and b/lock.png differ diff --git a/logintester.cpp b/logintester.cpp new file mode 100644 index 0000000..1fabc67 --- /dev/null +++ b/logintester.cpp @@ -0,0 +1,63 @@ +#include "logintester.h" +#include "ui_logintester.h" + +LoginTester::LoginTester(QString Benutzername, + QString Passwort, + int maxcount, + QWidget *parent) : + QDialog(parent, Qt::FramelessWindowHint), + ui(new Ui::LoginTester) +{ + ui->setupUi(this); + ui->button->hide(); + + counter = 0; + this->maxcount = maxcount; + this->Benutzername = Benutzername; + this->Passwort = Passwort; + manager = new QNetworkAccessManager(qApp); + + QObject::connect(manager, SIGNAL(authenticationRequired(QNetworkReply*, QAuthenticator*)), this, SLOT(authenticate(QNetworkReply*, QAuthenticator*))); + QObject::connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(finish(QNetworkReply*))); + QTimer::singleShot(100, this, SLOT(start())); +} + +LoginTester::~LoginTester() +{ + delete ui; +} + +void LoginTester::authenticate(QNetworkReply* , QAuthenticator* authenticator) +{ + if (counter < maxcount) + { + authenticator->setUser(Benutzername); + authenticator->setPassword(Passwort); + } + counter++; +} + +void LoginTester::start() +{ + manager->get(QNetworkRequest(QUrl("https://www2.elearning.rwth-aachen.de/foyer/summary/default.aspx"))); +} + +void LoginTester::finish(QNetworkReply* reply) +{ + if (reply->error()) + { + //ui->button->setText("Login fehlgeschlagen"); + QMessageBox messageBox; + messageBox.setText("Login fehlgeschlagen"); + messageBox.setInformativeText(reply->errorString()); + messageBox.setDetailedText(QString(reply->readAll())); + messageBox.setStandardButtons(QMessageBox::Ok); + messageBox.exec(); + reject(); + //QObject::connect(ui->button, SIGNAL(clicked()), this, SLOT(reject())); + } + else + accept(); +// QObject::connect(ui->button, SIGNAL(clicked()), this, SLOT(accept())); +// ui->button->show(); +} diff --git a/logintester.h b/logintester.h new file mode 100644 index 0000000..a2aa718 --- /dev/null +++ b/logintester.h @@ -0,0 +1,46 @@ +#ifndef LOGINTESTER_H +#define LOGINTESTER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Ui { + class LoginTester; +} + +class LoginTester : public QDialog +{ + Q_OBJECT + +public: + explicit LoginTester(QString Benutername, + QString Passwort, + int maxcount, + QWidget *parent = 0); + ~LoginTester(); + +private: + Ui::LoginTester *ui; + QNetworkAccessManager* manager; + + int counter; + int maxcount; + + QString Benutzername; + QString Passwort; + +private slots: + void authenticate(QNetworkReply*, QAuthenticator*); + void finish(QNetworkReply*); + void start(void); +}; + +#endif // LOGINTESTER_H diff --git a/logintester.ui b/logintester.ui new file mode 100644 index 0000000..d5f8677 --- /dev/null +++ b/logintester.ui @@ -0,0 +1,59 @@ + + + LoginTester + + + + 0 + 0 + 200 + 50 + + + + Dialog + + + + + 0 + -1 + 201 + 51 + + + + + 12 + + + + Teste Logindaten... + + + Qt::AlignCenter + + + + + + 10 + 5 + 180 + 40 + + + + + + + Login erfolgreich + + + false + + + + + + diff --git a/magnifier.ico b/magnifier.ico new file mode 100644 index 0000000..4b031a6 Binary files /dev/null and b/magnifier.ico differ diff --git a/magnifier.png b/magnifier.png new file mode 100644 index 0000000..2f0581e Binary files /dev/null and b/magnifier.png differ diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..1bd8f8a --- /dev/null +++ b/main.cpp @@ -0,0 +1,9 @@ +#include +#include "hauptfenster.h" + +int main(int argv, char **args) +{ + QApplication qtApplikation(argv, args); + Hauptfenster programm; + return qtApplikation.exec(); +} diff --git a/mysortfilterproxymodel.cpp b/mysortfilterproxymodel.cpp new file mode 100644 index 0000000..21266a5 --- /dev/null +++ b/mysortfilterproxymodel.cpp @@ -0,0 +1,29 @@ +#include "mysortfilterproxymodel.h" + +MySortFilterProxyModel::MySortFilterProxyModel(QObject *parent) + :QSortFilterProxyModel(parent) +{ +} + +void MySortFilterProxyModel::setMaximumSize(const qint32 size) +{ + maxSize = size*1024*1024; + invalidateFilter(); +} + +void MySortFilterProxyModel::setMaximumSizeFilter(const bool filter) +{ + maxSizeFilter = filter; + invalidateFilter(); +} + +bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const +{ + QStandardItemModel* source = (QStandardItemModel*) sourceModel(); + QModelIndex index = source->index(sourceRow, 0, sourceParent); + Strukturelement* item = (Strukturelement*)source->itemFromIndex(index); + + if (maxSizeFilter) + return (item->getSize() <= maxSize); + return true; +} diff --git a/mysortfilterproxymodel.h b/mysortfilterproxymodel.h new file mode 100644 index 0000000..8694075 --- /dev/null +++ b/mysortfilterproxymodel.h @@ -0,0 +1,39 @@ +#ifndef MYSORTFILTERPROXYMODEL_H +#define MYSORTFILTERPROXYMODEL_H + +#include +#include +#include + +class MySortFilterProxyModel : public QSortFilterProxyModel +{ +public: + MySortFilterProxyModel(QObject *parent = 0); + +// QDate filterMinimumDate() const { return minDate; } +// void setFilterMinimumDate(const QDate &date); + +// QDate filterMaximumDate() const { return maxDate; } +// void setFilterMaximumDate(const QDate &date); + + qint32 filterMaximumSize() const { return maxSize; } + void setMaximumSize(const qint32 size); + + void setMaximumSizeFilter(const bool filter); + + protected: + bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const; +// bool lessThan(const QModelIndex &left, const QModelIndex &right) const; + + private: +// bool dateInRange(const QDate &date) const; + bool sizeInRange(const qint32 size) const; + + qint32 maxSize; + bool maxSizeFilter; + +// QDate minDate; +// QDate maxDate; +}; + +#endif // MYSORTFILTERPROXYMODEL_H diff --git a/refresh.png b/refresh.png new file mode 100644 index 0000000..00b80a1 Binary files /dev/null and b/refresh.png differ diff --git a/strukturelement.cpp b/strukturelement.cpp new file mode 100644 index 0000000..bd29293 --- /dev/null +++ b/strukturelement.cpp @@ -0,0 +1,109 @@ +#include "strukturelement.h" +#include "datei.h" + +Strukturelement::Strukturelement(QString name, QUrl url, MyItemType type) + :QStandardItem(name), einschliessen(true), url(url), typeEX(type) +{ + size = 0; +} + +qint32 Strukturelement::getSize() const +{ + return size; +} + +QVariant Strukturelement::data(int role) const +{ + if (role == includeRole) + { + return einschliessen; + } + else if (role == urlRole) + { + return url; + } + else if (role == sizeRole) + { + return size; + } + else if (role == dateRole) + { + return zeit; + } + else if (role == Qt::StatusTipRole) + { + QString tooltip; + + if (typeEX == fileItem) + { + tooltip.append(text() % " - "); + if (size > 1048576) + tooltip.append(QString::number(size/1048576.0,'f',2) % " MB"); + else if(size > 1024) + tooltip.append(QString::number(size/1024.0,'f',2) % " KB"); + else + tooltip.append(QString::number(size) % " Byte"); + + tooltip.append(" - " % ((Datei*)this)->GetZeit().toString("ddd dd.MM.yy hh:mm")); + + return tooltip; + } + return tooltip; + } + else if (role == Qt::FontRole) + { + if (typeEX == courseItem) + { + QFont BoldFont; + BoldFont.setBold(true); + return BoldFont; + } + } + else if(role == Qt::ForegroundRole) + { + if (einschliessen) + return QBrush(Qt::black); + else + return QBrush(Qt::red); + } + return QStandardItem::data(role); +} + +bool Strukturelement::operator< (const QStandardItem& other) const +{ + if ((this->size == 0) && ((((Strukturelement*)(&other))->size) != 0)) + return true; + else if ((this->size != 0) && ((((Strukturelement*)(&other))->size) == 0)) + return false; + else + return (this->text().toLower() < (((Strukturelement*)(&other))->text()).toLower()); +} + +int Strukturelement::type() const +{ + return typeEX; +} + +void Strukturelement::setData(const QVariant &value, int role) +{ + if (role == includeRole) + { + this->einschliessen = value.toBool(); + } + else if (role == urlRole) + { + this->url = value.toUrl(); + } + else if (role == sizeRole) + { + this->size = value.toInt(); + } + else if (role == dateRole) + { + this->zeit = value.toDateTime(); + } + else + { + QStandardItem::setData(value, role); + } +} diff --git a/strukturelement.h b/strukturelement.h new file mode 100644 index 0000000..6c09d0b --- /dev/null +++ b/strukturelement.h @@ -0,0 +1,51 @@ +#ifndef STRUKTURELEMENT_H +#define STRUKTURELEMENT_H +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum MyItemType +{ + semesterItem = 1000, + courseItem = 1001, + directoryItem = 1002, + fileItem = 1003 +}; + +enum MyItemDataRole +{ + sizeRole = 32, + urlRole = 33, + dateRole = 34, + includeRole = 35 +}; + +class Strukturelement : public QStandardItem +{ +public: + Strukturelement(QString name, QUrl url, MyItemType typeEX); + qint32 getSize() const; + + int type() const; + + bool operator< (const QStandardItem& other) const; + + void setData(const QVariant &value, int role = Qt::UserRole + 1 ); + QVariant data(int role = Qt::UserRole + 1) const; + +protected: + bool einschliessen; + qint32 size; + QUrl url; + QDateTime zeit; + MyItemType typeEX; + +}; + +#endif // STRUKTURELEMENT_H diff --git a/tick.png b/tick.png new file mode 100644 index 0000000..b37c4a1 Binary files /dev/null and b/tick.png differ