#include "dialog.h"
#include <QMessageBox>
#include <QDebug>
#include <QRegExp>
#include <QFile>
#include <QProcess>
#include <QTimer>
#include <QDesktopWidget>
#include <QDateTime>
#include <QTemporaryFile>
#include "ui_dialog.h"
#include "sessiontreeitem.h"
#include "globals.h"
#include "vsession.h"
#include "choosersettings.h"
Dialog::Dialog(QWidget *parent)
: QDialog(parent), ui(new Ui::Dialog) {
model_[0] = new SessionTreeModel(parent);
model_[1] = new SessionTreeModel(parent);
model_[2] = new SessionTreeModel(parent);
ui->setupUi(this);
tabs_[0] = ui->tabButtonLocal;
tabs_[1] = ui->tabButtonMyClasses;
tabs_[2] = ui->tabButtonAllClasses;
strings_[STR_LOADING] = QCoreApplication::instance()->translate("Dialog", "Loading...");
strings_[STR_URL_ERROR] = QCoreApplication::instance()->translate("Dialog", "URL Error");
strings_[STR_NO_ITEMS] = QCoreApplication::instance()->translate("Dialog", "No Items");
pvsSettings_ = NULL;
ui->PVSOptionsGroupBox->hide();
// Re-center dialog every second to account for resolution changes
QRect desktopRect = QApplication::desktop()->availableGeometry(this);
oldCenter_ = desktopRect.center();
centerTimer_ = new QTimer(this);
connect(centerTimer_, SIGNAL(timeout()), this, SLOT(onCenterTimer()));
centerTimer_->start(1000);
activeTab_ = 2;
ui->tabButtonAllClasses->setChecked(true);
ui->helpBox->hide();
ui->newsBox->hide();
this->addStatusString(STR_LOADING);
QObject::connect(ui->treeView->selectionModel(), SIGNAL(currentChanged ( const QModelIndex&, const QModelIndex&)),
this, SLOT(treeView_selectionChanged(const QModelIndex&, const QModelIndex&)));
this->onTabButtonChanged(2);
}
Dialog::~Dialog() {
delete ui;
delete model_[0];
delete model_[1];
delete model_[2];
}
void Dialog::changeEvent(QEvent *e) {
QDialog::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
void Dialog::on_treeView_activated(QModelIndex index) {
// this method gets called when a Session has been activated
SessionTreeItem* item =
static_cast<SessionTreeItem*>(index.internalPointer());
const Session* s(item->session());
if (!s) {
// no valid session has been selected, do nothing
return;
}
// Run session start script
if (QFile::exists(sessionStartScript)) {
QProcess scriptProcess;
scriptProcess.start(sessionStartScript, QIODevice::ReadOnly);
scriptProcess.waitForFinished();
scriptProcess.close();
}
if (s->run()) {
writePVSSettings();
ChooserSettings::setSetting("last-session", (s->shortDescription()));
ChooserSettings::setSetting("last-tab", QString::number(activeTab_));
setVisible(false);
} else {
QMessageBox::warning(
this, trUtf8("vmchooser"),
trUtf8("Vmchooser failed to run the selected session!"));
}
}
void Dialog::addItems(const QList<Session*>& entries, int tab) {
if (tab < 0 || tab > 2) {
return;
}
this->model_[tab]->addItems(entries);
tabs_[tab]->setEnabled(this->model_[tab]->rowCount() != 0);
if (tab == activeTab_) {
setListModel(this->model_[tab]);
}
}
void Dialog::addStatusString(const int status) {
if (status < 0 || status >= STR__MAX)
return;
this->model_[1]->addLabelItem(strings_[status]);
this->model_[2]->addLabelItem(strings_[status]);
tabs_[1]->setEnabled(this->model_[1]->rowCount() > 1);
tabs_[2]->setEnabled(this->model_[2]->rowCount() > 1);
}
void Dialog::removeStatusString(const int status) {
if (status < 0 || status >= STR__MAX)
return;
this->model_[1]->removeItem(strings_[status]);
this->model_[2]->removeItem(strings_[status]);
tabs_[1]->setEnabled(this->model_[1]->rowCount() > 1);
tabs_[2]->setEnabled(this->model_[1]->rowCount() > 1);
}
void Dialog::on_pushButtonAbort_clicked() {
close();
}
void Dialog::on_pushButtonStart_clicked() {
this->on_treeView_activated(ui->treeView->selectionModel()->currentIndex());
}
void Dialog::readPVSSettings() {
if (!pvsSettings_) return;
QString value;
value = pvsSettings_->value("Permissions/vnc_lecturer").toString();
if (value == "rw") {
ui->comboBoxLecturer->setCurrentIndex(2);
} else if (value == "ro") {
ui->comboBoxLecturer->setCurrentIndex(1);
} else {
ui->comboBoxLecturer->setCurrentIndex(0);
}
value = pvsSettings_->value("Permissions/vnc_other").toString();
if (value == "rw") {
ui->comboBoxOthers->setCurrentIndex(2);
} else if (value == "ro") {
ui->comboBoxOthers->setCurrentIndex(1);
} else {
ui->comboBoxOthers->setCurrentIndex(0);
}
}
void Dialog::writePVSSettings() {
if (!pvsSettings_) return;
int accessLecturer = ui->comboBoxLecturer->currentIndex();
if (accessLecturer == 2) {
pvsSettings_->setValue("Permissions/vnc_lecturer", "rw");
} else if (accessLecturer == 1) {
pvsSettings_->setValue("Permissions/vnc_lecturer", "ro");
} else {
pvsSettings_->setValue("Permissions/vnc_lecturer", "no");
}
int accessOthers = ui->comboBoxOthers->currentIndex();
if (accessOthers == 2) {
pvsSettings_->setValue("Permissions/vnc_other", "rw");
} else if (accessOthers == 1) {
pvsSettings_->setValue("Permissions/vnc_other", "ro");
} else {
pvsSettings_->setValue("Permissions/vnc_other", "no");
}
pvsSettings_->sync();
}
void Dialog::on_comboBoxLecturer_currentIndexChanged(int index) {
// TODO (Jan): may others have more access than lecturer?
if (index < ui->comboBoxOthers->currentIndex()) {
ui->comboBoxOthers->setCurrentIndex(index);
}
}
void Dialog::on_comboBoxOthers_currentIndexChanged(int index) {
// TODO (Jan): may others have more access than lecturer?
if (index > ui->comboBoxLecturer->currentIndex()) {
ui->comboBoxLecturer->setCurrentIndex(index);
}
}
bool Dialog::selectSession(const QString& name) {
QModelIndex root(ui->treeView->rootIndex());
for (int tab = 0; tab <= 2; ++tab) {
for (int i = 0; i < model_[tab]->rowCount(root); ++i) {
QModelIndex index = model_[tab]->index(i, 0, root);
if (!index.isValid()) {
break;
}
SessionTreeItem* item = static_cast<SessionTreeItem*>(index.internalPointer());
const Session* s(item->session());
if (!s) {
continue;
}
if (s->shortDescription() == name) {
// change the tab
onTabButtonChanged(tab);
// set selection
ui->treeView->selectionModel()->clearSelection();
ui->treeView->selectionModel()
->setCurrentIndex(index, QItemSelectionModel::Select);
return true;
}
}
}
return false;
}
void Dialog::selectPreviousSession() {
if (!ChooserSettings::getSetting("last-session").isEmpty()) {
ui->treeView->clearSelection();
if (!selectSession(ChooserSettings::getSetting("last-session"))) {
// could not find last session, change to last used tab
this->onTabButtonChanged(ChooserSettings::getSetting("last-tab").toInt());
}
}
setListModel(this->model_[this->activeTab_]);
}
void Dialog::startSession(const QString& name) {
autoStartEntry_ = name;
}
void Dialog::showSettingsPVS() {
pvsSettings_ = new QSettings("openslx", "pvs", this);
QStringList accessOptions;
accessOptions << trUtf8("None") << trUtf8("View Only") << trUtf8("Full");
ui->comboBoxLecturer->insertItems(0, accessOptions);
ui->comboBoxOthers->insertItems(0, accessOptions);
readPVSSettings();
ui->PVSOptionsGroupBox->show();
}
void Dialog::setTheme() {
QString label_l_style, label_r_style;
QString backgroundColor, imageLeft, imageRight;
QString themePathBase, themePathIni, themePathImgLeft, themePathImgRight;
if (theme.isEmpty()) return;
themePathBase = QString("%1/%2/").arg(VMCHOOSER_THEME_BASE).arg(theme);
themePathIni = QString("%1%2.ini").arg(themePathBase).arg(theme);
if (!QFile::exists(themePathIni)) return;
QSettings themeSettings(themePathIni, QSettings::IniFormat);
backgroundColor = themeSettings.value("background-color").toString();
imageLeft = themeSettings.value("image-left").toString();
imageRight = themeSettings.value("image-right").toString();
themePathImgLeft = QString("%1%2").arg(themePathBase).arg(imageLeft);
themePathImgRight = QString("%1%2").arg(themePathBase).arg(imageRight);
QRegExp re;
ui->label_l->setPixmap(QPixmap(themePathImgLeft));
ui->label_r->setPixmap(QPixmap(themePathImgRight));
label_l_style = ui->label_l->styleSheet();
label_r_style = ui->label_r->styleSheet();
backgroundColor.prepend("\\1").append("\\2");
label_l_style.replace(QRegExp("(.*background-color:)#[^;]*(;.*)"), backgroundColor);
label_r_style.replace(QRegExp("(.*background-color:)#[^;]*(;.*)"), backgroundColor);
//qDebug() << label_r_style << label_l_style;
ui->label_l->setStyleSheet(label_l_style);
ui->label_r->setStyleSheet(label_r_style);
}
void Dialog::onCenterTimer() {
if (!autoStartEntry_.isEmpty()) {
if (this->selectSession(autoStartEntry_)) {
this->on_treeView_activated(ui->treeView->selectionModel()->currentIndex());
} else {
QMessageBox::critical(this, "Autostart", QString::fromUtf8("Konnte %1 nicht starten.").arg(autoStartEntry_));
}
autoStartEntry_.clear();
return;
}
// center dialog on primary screen
QRect desktopRect = QApplication::desktop()->availableGeometry(this);
QPoint center = desktopRect.center();
if (center != oldCenter_) {
this->move(center.x() - this->width() / 2, center.y() - this->height() / 2);
oldCenter_ = center;
}
}
void Dialog::addSessionsAfterDownload(QNetworkReply* reply) {
QString temp_filename;
if (reply->error() != QNetworkReply::NoError) {
if (debugMode) {
qDebug() << "Error reading from URL: " << reply->error();
}
QFile backup_file(xml_filename);
if (!backup_file.open(QIODevice::ReadOnly)) {
if (debugMode) {
qDebug() << "Cannot read backup file " << xml_filename << " either";
}
this->removeStatusString(STR_LOADING);
this->addStatusString(STR_URL_ERROR);
return;
}
if (debugMode) {
qDebug() << "Using backup file " << xml_filename;
}
backup_file.close();
temp_filename = xml_filename;
} else {
QByteArray data = reply->readAll();
// write xml to temporary file
temp_filename = QDir::tempPath() + "/vmchooser2/vmchooser-XXXXXX.xml";
QTemporaryFile tmpfile(temp_filename);
if (!tmpfile.open() || tmpfile.write(data) == -1) {
return;
}
tmpfile.close();
tmpfile.setAutoRemove(false);
temp_filename = tmpfile.fileName();
}
QList<Session*> sessions = VSession::readXmlFile(temp_filename);
this->removeStatusString(STR_LOADING);
if (!sessions.isEmpty()) {
qSort(sessions.begin(), sessions.end(), myLessThan);
this->addItems(sessions, 2); // TODO: No magic number; handle user specific classes
} else {
this->addStatusString(STR_NO_ITEMS);
}
// select last-session
selectPreviousSession();
}
void Dialog::treeView_selectionChanged(const QModelIndex& current, const QModelIndex&) {
SessionTreeItem* item =
static_cast<SessionTreeItem*>(current.internalPointer());
const Session* s(item->session());
if (!s) {
if (debugMode) {
qDebug() << "invalid selection";
}
// no valid session has been selected, do nothing
return;
}
if (s->type() == Session::VSESSION) {
const VSession* vs = (VSession*) s;
ui->label_name->setText(vs->getAttribute("short_description", "param"));
ui->label_name->setToolTip(vs->getAttribute("short_description", "param"));
ui->label_creator->setText(vs->getAttribute("creator", "param"));
ui->label_creator->setToolTip(vs->getAttribute("creator", "param"));
ui->label_os->setText(vs->getAttribute("os", "param"));
ui->label_os->setToolTip(vs->getAttribute("os", "param"));
QString description(vs->getAttribute("long_description", "param") + "\n\nKeywords: ");
for (int i = 0; i < vs->keywords().length(); ++i) {
description += vs->keywords()[i] + ", ";
}
ui->textBrowser->setText(description);
} else {
ui->label_name->setText(s->shortDescription());
ui->label_creator->setText("");
ui->label_os->setText(QCoreApplication::instance()->translate("Dialog", "Native Linux"));
ui->textBrowser->setPlainText(QCoreApplication::instance()->translate("Dialog", "Linux X session running on this machine without virtualization."));
}
}
void Dialog::on_tabButtonLocal_clicked() {
onTabButtonChanged(0);
}
void Dialog::on_tabButtonMyClasses_clicked() {
onTabButtonChanged(1);
}
void Dialog::on_tabButtonAllClasses_clicked() {
onTabButtonChanged(2);
}
void Dialog::onTabButtonChanged(int tab) {
if (tab < 0 || tab > 2) {
// no valid button
return;
}
// give focus to treeView
ui->treeView->setFocus();
// Update pressed status of buttons
for (int i = 0; i < 3; ++i) {
tabs_[i]->setChecked(tab == i);
}
// clear filter if necessary
if (activeTab_ != tab) {
this->ui->filterEdit->setText("");
}
// load the new list
setListModel(model_[tab]);
this->activeTab_ = tab;
}
void Dialog::on_filterEdit_textChanged() {
SessionTreeModel *newModel;
// filter the current model
if (ui->filterEdit->text() != "" && ui->filterEdit->text().replace(" ", "").length() > 2) {
newModel = new SessionTreeModel(this);
newModel->addItems(this->model_[activeTab_]->lookForItem(ui->filterEdit->text()));
} else {
newModel = model_[activeTab_];
}
setListModel(newModel);
}
void Dialog::setListModel(QAbstractItemModel *model) {
if (ui->treeView->model() == model_[0] || ui->treeView->model() == model_[1] || ui->treeView->model() == model_[2]) {
} else {
ui->treeView->model()->deleteLater();
}
ui->treeView->setModel(model);
// reconnect the treeModel
QObject::connect(ui->treeView->selectionModel(), SIGNAL(currentChanged ( const QModelIndex&, const QModelIndex&)),
this, SLOT(treeView_selectionChanged(const QModelIndex&, const QModelIndex&)));
if (ui->treeView->selectionModel()->selectedRows(0).count() == 0) {
ui->treeView->selectionModel()->setCurrentIndex(ui->treeView->model()->index(0, 0, ui->treeView->rootIndex()), QItemSelectionModel::Select);
}
}
void Dialog::on_helpNewsButton_clicked() {
if (ui->helpBox->isVisible()) {
ui->helpBox->hide();
ui->newsBox->hide();
} else {
ui->helpBox->show();
ui->newsBox->show();
}
}
void Dialog::addNewsAfterDownload(QNetworkReply* reply) {
if (reply->error() != QNetworkReply::NoError) {
if (debugMode) {
qDebug() << "Could not get news. Try to get cached news.";
}
// try to get cached news
QFile backup_file(news_backup_filename);
if (!backup_file.open(QIODevice::ReadOnly)) {
if (debugMode) {
qDebug() << "Cannot read backup file " << news_backup_filename << " either";
}
this->ui->newsTextBrowser->setText(QCoreApplication::instance()->translate("Dialog", "Could not get news."));
return;
}
if (debugMode) {
qDebug() << "Used backup file " << news_backup_filename;
}
backup_file.close();
return;
}
QByteArray data = reply->readAll();
QDomDocument doc;
if (!doc.setContent(data)) {
qDebug() << "News XML contains errors.";
return;
}
QDomElement newsNode = doc.firstChildElement("news");
QDateTime timestamp;
timestamp.setTime_t(newsNode.firstChildElement("date").text().toInt());
// format and print news
ui->newsTextBrowser->setText(QString("<p style='font-size:16px; margin-bottom: 2px;'>" + newsNode.firstChildElement("headline").text() + "</p> <small>"
+ timestamp.toString(Qt::SystemLocaleShortDate) + "</small><p>"
+ newsNode.firstChildElement("info").text() + "</p>"));
if (ChooserSettings::getSetting("last-news").toUInt() < timestamp.toTime_t()) {
// show news if not seen before
on_helpNewsButton_clicked();
}
// update ini
ChooserSettings::setSetting("last-news", QString::number(timestamp.toTime_t()));
// make backup
QFile file(news_backup_filename);
if (!file.open(QIODevice::WriteOnly)) {
if (debugMode) {
qDebug() << "Could not write XML to " << news_backup_filename;
}
return;
}
if (file.write(data) != data.length()) {
return;
}
if (!file.setPermissions(QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther)) {
if (debugMode) {
qDebug() << "Could not change permissions of file: " << news_backup_filename;
}
}
file.close();
}
void Dialog::addHelpAfterDownload(QNetworkReply* reply) {
if (reply->error() != QNetworkReply::NoError) {
if (debugMode) {
qDebug() << "Could not get help xml. Try to get cached help...";
}
// try to get cached news
QFile backup_file(help_backup_filename);
if (!backup_file.open(QIODevice::ReadOnly)) {
if (debugMode) {
qDebug() << "Cannot read backup file " << help_backup_filename << " either";
}
this->ui->helpTextBrowser->setText(QCoreApplication::instance()->translate("Dialog", "Could not get help."));
return;
}
if (debugMode) {
qDebug() << "Used backup file " << help_backup_filename;
}
backup_file.close();
return;
}
QByteArray data = reply->readAll();
QDomDocument doc;
if (!doc.setContent(data)) {
if (debugMode) {
qDebug() << "Help file contains errors.";
}
return;
}
ui->helpTextBrowser->setText(QString(data));
// make backup
QFile file(help_backup_filename);
if (!file.open(QIODevice::WriteOnly)) {
if (debugMode) {
qDebug() << "Could not write XML to " << help_backup_filename;
}
return;
}
if (file.write(data) != data.length()) {
return;
}
if (!file.setPermissions(QFile::ReadUser | QFile::ReadGroup | QFile::ReadOther | QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther)) {
if (debugMode) {
qDebug() << "Could not change permissions of file: " << help_backup_filename;
}
}
file.close();
}
void Dialog::keyPressEvent(QKeyEvent* event) {
switch(event->key()) {
case Qt::Key_Return: this->on_pushButtonStart_clicked(); break;
case Qt::Key_Escape: this->on_pushButtonAbort_clicked(); break;
case Qt::Key_H: this->on_helpNewsButton_clicked(); break;
}
}