summaryrefslogblamecommitdiffstats
path: root/src/dialog.cpp
blob: 009da02e010a6f66f78ffcfc5757e5875a5bf104 (plain) (tree)
1
2
3
4
5
6
7
8
9








                         
                    
                         

                      

                            
                     
                            


                                           



                                             








                                                                         
                                                                          
                              
 

                                         
                                      
 


                            
                            


                                                                                                                      



                   


                     


































                                                                     
                                                                             
                                                                            








                                                                         




                                                                

 




                                                          

 




                                                       

 





































































                                                                                




                                                                   
                         








                                                                                                       
                                                                                 




                                                                                                      
     
 



                                      

                                                                     



                                                                                                  
         








                                                         
                                                                             








































                                                                                            
                              

















                                                                                                                         
                                                             

                              
                                                       


                                                                                 
 
                                                


                                                             
                                                                                                    
                         

                                                                                                              

                               
                                
                                                                        
                 
                                    
 
                                                                               
                                                                    
                                            
                
                                                   
 








                                                                                      
         
 
                                                                        
 
                                                                                             

                                  
                                                                    
                                            
                
                                                                                                     
         


                                

 





                                                                                        


                                                





                                                         
 








                                                                                   





                                                                                              







                                                                                                                     





















                                               

                                                            
                                                     

                                                           
                                                  

                                                      
                                                         
                                                           
                                                 


                                                          
                                                          
                                                 

         




                                                  

                                  
                              





                                          
                                                                                                   




                                                                                                 
                               




                                                                                                                             
                                                     

                                      




                                                                                                                      



                                                                                                                                                            

 








                                          



                                                         














                                                                                                                                     
                 
                                    











                                                                           




                                                                                                                                                           






                                                                                    


















                                                                                                                                                     




                                                         
                                                                                        
                 














                                                                                                                                     

                       
 
                                           
                         
 
                                    


                                                                 



                                                    


















                                                                                                                                                     
 
 





                                                                          
 
#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);

    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 = 0;
    ui->tabButtonLocal->setChecked(true);
    ui->filterEdit->setEnabled(false);

	ui->helpBox->hide();
	ui->newsBox->hide();

    setListModel(model_[0]);

    QObject::connect(ui->treeView->selectionModel(), SIGNAL(currentChanged ( const QModelIndex&, const QModelIndex&)),
    		this, SLOT(treeView_selectionChanged(const QModelIndex&, const QModelIndex&)));
}

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);
}

void Dialog::addLabelItem(const QString& label, int tab) {
	if (tab < 0 || tab > 2) {
		return;
	}
	this->model_[tab]->addLabelItem(label);
}

void Dialog::removeItem(const QString& name, int tab) {
	if (tab < 0 || tab > 2) {
		return;
	}
	this->model_[tab]->removeItem(name);
}

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());
		}
	}
}

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->removeItem(QCoreApplication::instance()->translate("Dialog", "Loading..."), 1);
			this->addLabelItem(QCoreApplication::instance()->translate("Dialog", "URL Error"), 1);
			return;
		}
		if (debugMode) {
			qDebug() << "Used backup file " << xml_filename;
		}
		backup_file.close();

		QList<Session*> sessions = VSession::readXmlFile(xml_filename);
		qSort(sessions.begin(), sessions.end(), myLessThan);
		this->addItems(sessions, 1);
	} 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->removeItem(QCoreApplication::instance()->translate("Dialog", "Loading..."), 1);

	if (!sessions.isEmpty()) {
		qSort(sessions.begin(), sessions.end(), myLessThan);
		this->addItems(sessions, 1);
	} else {
		this->addLabelItem(QCoreApplication::instance()->translate("Dialog", "No Items"), 1);
	}

	// 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"));
    	ui->textBrowser->setPlainText(QCoreApplication::instance()->translate("Dialog", "Running on this machine."));
    }
}

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();

	// when button was pressed disable the other buttons
	if (tab == 0) {
		ui->tabButtonLocal->setChecked(true);
		ui->tabButtonMyClasses->setChecked(false);
		ui->tabButtonAllClasses->setChecked(false);
		ui->filterEdit->setEnabled(false);
	} else if (tab == 1) {
		ui->tabButtonLocal->setChecked(false);
		ui->tabButtonMyClasses->setChecked(true);
		ui->tabButtonAllClasses->setChecked(false);
		ui->filterEdit->setEnabled(true);
	} else {
		ui->tabButtonLocal->setChecked(false);
		ui->tabButtonMyClasses->setChecked(false);
		ui->tabButtonAllClasses->setChecked(true);
		ui->filterEdit->setEnabled(true);
	}

	// 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()->clearSelection();
		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 " << xml_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 " << xml_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;
	}
}