source: ogBrowser-Git/src/mainwindow.cpp @ 21e8f4c

jenkinsmain
Last change on this file since 21e8f4c was 476581b, checked in by Vadim Troshchinskiy Shmelev <vtroshchinskiy@…>, 16 months ago

Add desktop file parser

  • Property mode set to 100644
File size: 17.4 KB
RevLine 
[050d67a]1#include "mainwindow.h"
[dae65b7]2#include <QtWebEngineWidgets>
[050d67a]3#include <QStringList>
[dae65b7]4#include <QWebEngineView>
[050d67a]5#include <QDockWidget>
6#include <QtDebug>
[dae65b7]7#include <QWebEnginePage>
[050d67a]8#include <QProcess>
9#include <QTextEdit>
10#include <QMessageBox>
11#include <QPushButton>
12#include <QDateTime>
[23de05d]13#include <QProgressBar>
14#include <QTabWidget>
[2e2ba31]15#include <QLineEdit>
[2518513]16#include <QNetworkReply>
17#include <QSslError>
[75617e0]18#include <QTimer>
[07ea3f8]19#include <QRegularExpression>
20#include <QStringList>
21#include <QString>
22
[050d67a]23#include "qtermwidget.h"
[476581b]24#include "KeyboardTranslator.h"
25
[099ac5d]26#include "digitalclock.h"
[07ea3f8]27#include "ogurlhandler.h"
[476581b]28#include "ogwebpage.h"
29#include "desktopparser.h"
[050d67a]30
31#define BUFFERSIZE 2048
[9d6a1e3]32#define REGEXP_STRING "^\\[(\\d+)\\]"
[050d67a]33
[75617e0]34#define CURRENT_TIME() QDateTime::currentDateTime().toString("dd/MM/yyyy hh:mm:ss")
[050d67a]35
36MainWindow::MainWindow(QWidget *parent)
[dae65b7]37    : QMainWindow(parent),m_web(new QWebEngineView()),m_output(new QTextEdit()),
[b93c220]38      m_logfile(0),m_logstream(0),m_numberTerminal(0)
[050d67a]39{
40    // Graphic
[099ac5d]41    setWindowTitle(tr("OpenGnsys Browser"));
[b93c220]42    setCentralWidget(m_web);
[0b5cc5a]43    readEnvironmentValues();
44
[07ea3f8]45    m_is_admin = qgetenv("ogactiveadmin") == "true";
[cad017d]46    m_kiosk_mode = qgetenv("OGKIOSKMODE") == "true";
[07ea3f8]47
[75617e0]48    // Open the log file for append
49    if(m_env.contains("OGLOGFILE") && m_env["OGLOGFILE"]!="")
50    {
51        QFile* m_logfile=new QFile(m_env["OGLOGFILE"]);
52        if(!m_logfile->open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Append))
53        {
54            delete m_logfile;
[6a71755]55            print(tr("El fichero de log no ha podido ser abierto: %1.").arg(m_env["OGLOGFILE"]));
[75617e0]56        }
57        else
58        {
59            m_logstream=new QTextStream(m_logfile);
60        }
61    }
62
[23de05d]63    // Output
[b93c220]64    m_output->setReadOnly(true);
[1b0403f]65    m_output->setFontPointSize(16);
[23de05d]66
[2e2ba31]67    // Button Dock
[23de05d]68    QDockWidget* dock=new QDockWidget();
[050d67a]69    dock->setAllowedAreas(Qt::BottomDockWidgetArea);
[23de05d]70    QWidget* dummy=new QWidget();
71    dummy->setMaximumHeight(0);
72    dock->setTitleBarWidget(dummy);
[050d67a]73
[23de05d]74    // TabWidget
[b93c220]75    m_tabs=new QTabWidget(dock);
[f885166]76    QPushButton *button=new QPushButton(tr("&Nueva Terminal"));
[2e2ba31]77    button->setFocusPolicy(Qt::TabFocus);
[b93c220]78    m_tabs->setCornerWidget(button);
79    m_tabs->setFocusPolicy(Qt::NoFocus);
[f885166]80    m_tabs->addTab(m_output,tr("Salida"));
[55d467e]81    slotCreateTerminal();
[0dff9e1]82    // Assign tabs to dock
[b93c220]83    dock->setWidget(m_tabs);
[0dff9e1]84    // Assign tabs dock to the mainwindow if admin mode is active
[07ea3f8]85    if(isAdmin())
[75617e0]86        addDockWidget(Qt::BottomDockWidgetArea,dock);
[050d67a]87
[2e2ba31]88    // Top Dock
89    dock=new QDockWidget();
90    dock->setAllowedAreas(Qt::TopDockWidgetArea);
91    QWidget* dummy2=new QWidget();
92    dummy2->setMaximumHeight(0);
93    dock->setTitleBarWidget(dummy2);
94    // WebBar
[b93c220]95    m_webBar=new QLineEdit(dock);
[0dff9e1]96    // WebBar to dock
[b93c220]97    dock->setWidget(m_webBar);
[0dff9e1]98    // Assign top dock to the mainwindow if admin mode is active
[07ea3f8]99    if(isAdmin())
[75617e0]100        addDockWidget(Qt::TopDockWidgetArea,dock);
[2e2ba31]101
[23de05d]102    // Status bar
103    QStatusBar* st=statusBar();
104    st->setSizeGripEnabled(false);
[c646cde]105    // OpenGnsys logo (or alternate text)
106    m_logo=new QLabel();
107    QPixmap logo;
[e9b8eab]108    if(logo.load("/opt/opengnsys/lib/pictures/oglogo.png"))
[75617e0]109        m_logo->setPixmap(logo);
[c646cde]110    else
[75617e0]111        m_logo->setText("OG");
[6538925]112    m_logo->setToolTip(tr("Proyecto OpenGnsys\nhttps://opengnsys.es"));
[c646cde]113    // Progress bar
[b93c220]114    m_progressBar=new QProgressBar(this);
[0dff9e1]115    m_progressBar->setRange(0,100);
[c646cde]116    // Connection speed
117    QString speed=readSpeed();
118    m_speedInfo=new QLabel(speed);
119    m_speedInfo->setAlignment(Qt::AlignCenter);
[e9b8eab]120    if(m_env.contains("DEFAULTSPEED") && m_env["DEFAULTSPEED"]!="")
[75617e0]121        if(speed.compare(m_env["DEFAULTSPEED"])!=0)
122            m_speedInfo->setStyleSheet("background-color: darkred; color: white; font-weight: bold;");
[c646cde]123    // Clock
[099ac5d]124    m_clock=new DigitalClock(this);
[050d67a]125
[b93c220]126    connect(m_web,SIGNAL(loadStarted()),this,SLOT(slotWebLoadStarted()));
127    connect(m_web,SIGNAL(loadFinished(bool)),this,SLOT(slotWebLoadFinished(bool)));
128    connect(m_web,SIGNAL(loadProgress(int)),this,SLOT(slotWebLoadProgress(int)));
[c646cde]129    connect(m_web,SIGNAL(urlChanged(const QUrl&)),this,SLOT(slotUrlChanged(const QUrl&)));
[2518513]130    // Ignore SSL errors.
[dae65b7]131
132
133    // Qindel:
134    //connect(m_web->page()->networkAccessManager(),
135//            SIGNAL(sslErrors(QNetworkReply*, const QList<QSslError> &)), this,
136//            SLOT(slotSslErrors(QNetworkReply*)));
[050d67a]137
138
[2e2ba31]139    // Dock signals
[55d467e]140    connect(button,SIGNAL(clicked()),this,SLOT(slotCreateTerminal()));
141
[d9df909]142    // All schemes need registering first, then their handlers.
143    registerScheme("command");
144    registerScheme("command+output");
145    registerScheme("command+confirm");
146    registerScheme("command+confirm+output");
147    registerScheme("command+output+confirm");
[07ea3f8]148
149
[476581b]150    auto &desktopParser = DesktopParser::getInstance();
151    QMap<QString, QString> schemes = desktopParser.getSchemes();
152
153    for(const QString scheme : schemes.keys()) {
154        if ( scheme == "http" || scheme == "https")
155            continue;
156
157        registerScheme(scheme);
158    }
159
160    /////////////////////////////////////////////////
161    // Register all handlers after the schemes
162    /////////////////////////////////////////////////
163
164    for(const QString scheme : schemes.keys()) {
165        if ( scheme == "http" || scheme == "https")
166            continue;
167
168        registerHandler(scheme, false, false, schemes[scheme]);
169    }
170
171
172
[07ea3f8]173    registerHandler("command", false, false);
174    registerHandler("command+output", false, true);
175    registerHandler("command+confirm", true, false);
176    registerHandler("command+confirm+output", true, true);
177    registerHandler("command+output+confirm", true, true);
178
179
[476581b]180    //QStringList arguments=QCoreApplication::arguments();
181
182    m_web->setPage( new OGWebPage(this));
183
184    OGCommandLineOptions &options = OGCommandLineOptions::getInstance();
185    QUrl url = QUrl(options.getUrl());
186
187    m_webBar->setText(url.toString());
188
189    qInfo() << "Page set to" << url;
190    m_web->load(url);
191
192
193
194
195
196
[07ea3f8]197
198
[476581b]199   // auto ktm = Konsole::KeyboardTranslatorManager::instance();
[07ea3f8]200
201
202
203    showMaximized();
204    showFullScreen();
[050d67a]205}
206
[cad017d]207void MainWindow::closeEvent(QCloseEvent *event) {
208    if (isKioskMode()) {
209        qInfo() << "Modo quiosco activado, ignorando intento de cerrar ventana";
210        event->ignore();
211    }
212}
213
214
[050d67a]215MainWindow::~MainWindow()
216{
[b93c220]217    if(m_logfile)
[050d67a]218    {
[b93c220]219        m_logfile->close();
220        delete m_logfile;
[050d67a]221    }
[b93c220]222    if(m_logstream)
223        delete m_logstream;
[050d67a]224}
225
[d9df909]226void MainWindow::registerScheme(const QString &name) {
227    QWebEngineUrlScheme scheme(name.toLatin1());
228    scheme.setSyntax(QWebEngineUrlScheme::Syntax::Path);
229    scheme.setDefaultPort(0);
230    scheme.setFlags(QWebEngineUrlScheme::LocalScheme);
231    QWebEngineUrlScheme::registerScheme(scheme);
232}
233
[07ea3f8]234
[476581b]235void MainWindow::registerHandler(const QString &commandName, bool confirm, bool returnOutput, const QString baseCommand) {
[07ea3f8]236    OGBrowserUrlHandlerCommand *handler = new OGBrowserUrlHandlerCommand(this);
237    connect(handler, &OGBrowserUrlHandlerCommand::command, this, &MainWindow::commandQueued);
238    handler->setAskConfirmation(confirm);
239    handler->setReturnOutput(returnOutput);
[476581b]240    handler->setBaseCommand(baseCommand);
241    handler->setScheme(commandName);
[07ea3f8]242    QWebEngineProfile::defaultProfile()->installUrlSchemeHandler(commandName.toLatin1(), handler);
243}
244
245void MainWindow::commandQueued(const QString &command, bool confirm, bool returnOutput) {
246    //PendingCommand cmd;
247
248    qInfo() << "Queued command:" << command;
249
250    if (confirm) {
251        QMessageBox msgBox;
252        msgBox.setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint);
[f885166]253        msgBox.setWindowTitle(tr("AVISO"));
[07ea3f8]254        msgBox.setIcon(QMessageBox::Question);
255        msgBox.setTextFormat(Qt::RichText);
[e6e629e]256        msgBox.setText(tr("La siguiente acción puede modificar datos o tardar varios minutos. El equipo no podrá ser utilizado durante su ejecución."));
[f885166]257        QPushButton *execButton = msgBox.addButton(tr("Ejecutar"), QMessageBox::ActionRole);
258        msgBox.addButton(tr("Cancelar"), QMessageBox::RejectRole);
[07ea3f8]259        msgBox.setDefaultButton(execButton);
260        msgBox.exec();
261
262        if (msgBox.clickedButton() != execButton) {
263            qInfo() << "User rejected running the command";
264            return;
265        }
266    }
267
268    if (returnOutput && !isAdmin()) {
269        int w=MainWindow::width(), h=MainWindow::height();
270        m_output->setWindowFlags(Qt::Window);
271        m_output->move(100, 100);
272        m_output->setFixedSize(w*0.8-100, h*0.8-100);
273        m_output->show();
274    }
275
276
277    m_command.command = command;
278    m_command.confirm = confirm;
279    m_command.returnOutput = returnOutput;
280
281
282
283
284    QStringList list=command.split(" ",Qt::SkipEmptyParts);
285    QString program=list.takeFirst();
286
287    m_command.process = new QProcess(this);
288    m_command.process->setReadChannel(QProcess::StandardOutput);
289    m_command.process->setEnvironment(QProcess::systemEnvironment());
290
291    // Process signals
292    connect(m_command.process, &QProcess::started,this, &MainWindow::slotProcessStarted);
293    connect(m_command.process, &QProcess::finished,this,&MainWindow::slotProcessFinished);
294    connect(m_command.process, &QProcess::errorOccurred, this,&MainWindow::slotProcessError);
295    connect(m_command.process, &QProcess::readyReadStandardOutput,this,&MainWindow::slotProcessOutput);
296    connect(m_command.process, &QProcess::readyReadStandardError,this,&MainWindow::slotProcessErrorOutput);
297
298
299    if(isAdmin()) {
300        m_output->setTextColor(QColor(Qt::darkGreen));
[6a71755]301        print(tr("Lanzando el comando: %1").arg(command));
[07ea3f8]302        m_output->setTextColor(QColor(Qt::black));
303    } else {
[6a71755]304        write(tr("Lanzando el comando: %1").arg(command));
[07ea3f8]305    }
306
307    m_command.process->start(program,list);
308    startProgressBar();
309
310}
311
[050d67a]312void MainWindow::slotWebLoadStarted()
313{
[9d8d163]314    startProgressBar();
[6a71755]315    m_progressBar->setFormat(tr("%p% Cargando"));
[050d67a]316}
317
318void MainWindow::slotWebLoadProgress(int progress)
319{
[b93c220]320    m_progressBar->setValue(progress);
[050d67a]321}
322
323void MainWindow::slotWebLoadFinished(bool ok)
324{
325    // If any error ocurred, show a pop up
326    // Sometimes when the url hasn't got a dot, i.e /var/www/pageweb,
327    // the return value is always true so we check the bytes received too
[07ea3f8]328    qWarning() << "Load finished. URL: " << m_web->url() << "; ok = " << ok;
329
330    finishProgressBar();
331
[050d67a]332}
333
[2e2ba31]334void MainWindow::slotUrlChanged(const QUrl &url)
335{
[b93c220]336    m_webBar->setText(url.toString());
[2e2ba31]337}
338
[2518513]339void MainWindow::slotSslErrors(QNetworkReply* reply)
340{
341    reply->ignoreSslErrors();
342}
343
[050d67a]344void MainWindow::slotProcessStarted()
345{
[9d8d163]346    startProgressBar();
[050d67a]347}
348
349void MainWindow::slotProcessOutput()
350{
[07ea3f8]351    m_command.process->setReadChannel(QProcess::StandardOutput);
[050d67a]352    char buf[BUFFERSIZE];
[07ea3f8]353    while((m_command.process->readLine(buf,BUFFERSIZE) > 0))
[050d67a]354    {
[9d8d163]355        QString s(buf);
[07ea3f8]356        qInfo() << "OUT: " << buf;
357
358        if(isAdmin())
[1b0403f]359        {
360            m_output->insertPlainText(tr("Proc. stdout: "));
361        }
362        print(s);
[9d8d163]363        captureOutputForStatusBar(s);
[050d67a]364    }
365}
366
367void MainWindow::slotProcessErrorOutput()
368{
[07ea3f8]369
370   // QProcess *process = qobject_cast<QProcess*>(sender());
371   // QVector<PendingCommand>::iterator it=std::find(m_commands.begin(), m_commands.end(), []())
372
373    m_command.process->setReadChannel(QProcess::StandardError);
[050d67a]374    char buf[BUFFERSIZE];
[07ea3f8]375    while((m_command.process->readLine(buf,BUFFERSIZE) > 0))
[050d67a]376    {
[1fc67a0]377        QString s(buf);
[07ea3f8]378        qInfo() << "ERR: " << buf;
379
380        if(isAdmin())
[1b0403f]381        {
382            m_output->insertPlainText(tr("Proc. stderr: "));
383        }
[2f7db25]384        m_output->setTextColor(QColor(Qt::darkBlue));
385        print(s);
386        m_output->setTextColor(QColor(Qt::black));
[050d67a]387    }
388}
389
[1b0403f]390void MainWindow::slotProcessFinished(int code, QProcess::ExitStatus status)
[050d67a]391{
[07ea3f8]392
393    qInfo() << "Finished: " << m_command.command << "with status" << status;
394
395    if(isAdmin())
[050d67a]396    {
[1b0403f]397        // Admin user: show process status
398        if(status==QProcess::NormalExit)
399        {
400            if(code > 0)
[59c8a0f]401            {
[1b0403f]402                m_output->setTextColor(QColor(Qt::darkRed));
[59c8a0f]403            }
[6a71755]404            print("\n"+tr("Fin del proceso. Valor de retorno: %1").arg(code));
[1b0403f]405        }
406        else
407        {
408            m_output->setTextColor(QColor(Qt::darkRed));
[6a71755]409            print("\n"+tr("El proceso ha fallado inesperadamente. Salida: %1").arg(code));
[1b0403f]410        }
411        m_output->setTextColor(QColor(Qt::black));
[050d67a]412    }
413    else
414    {
[1b0403f]415        // Non-admin user: show instruction to close the popup window
[6a71755]416        write(tr("Fin del proceso. Valor de retorno: %1").arg(code));
[1b0403f]417        m_output->setFontUnderline(true);
[6538925]418        print("\n\n"+tr("AVISO: Pulsar el botón superior derecho para cerrar (✖)"));
[1b0403f]419        m_output->setFontUnderline(false);
[050d67a]420    }
[75617e0]421    // On error, show a message box
[1b0403f]422    if(code > 0 && ! m_output->isActiveWindow())
423    {
[6a71755]424        showErrorMessage(tr("Código de salida: %1").arg(code));
[1b0403f]425    }
[9d8d163]426    finishProgressBar();
[050d67a]427}
428
429void MainWindow::slotProcessError(QProcess::ProcessError error)
430{
[07ea3f8]431    qCritical() << "Error: " << m_command.command << "with status" << error;
432
[75617e0]433    QString errorMsg;
[050d67a]434    switch(error)
435    {
436        case QProcess::FailedToStart:
[f885166]437            errorMsg=tr("Imposible lanzar el proceso.");
[b93c220]438            break;
439        case QProcess::WriteError:
[f885166]440            errorMsg=tr("Error de escritura en el proceso.");
[b93c220]441            break;
442        case QProcess::ReadError:
[f885166]443            errorMsg=tr("Error de lectura del proceso.");
[050d67a]444            break;
445        // No capturo crashed porque la pillo por finished
446        case QProcess::Crashed:
447        case QProcess::Timedout:
[b93c220]448            break;
[050d67a]449        case QProcess::UnknownError:
450        default:
[f885166]451            errorMsg=tr("Error desconocido.");
[050d67a]452            break;
453    }
[75617e0]454    // Print error and show message box with timeout.
455    if(!errorMsg.isNull()) {
456        m_output->setTextColor(QColor(Qt::darkRed));
457        print(errorMsg);
458        m_output->setTextColor(QColor(Qt::black));
459        showErrorMessage(errorMsg);
460    }
[c70d4be]461    finishProgressBar();
[050d67a]462}
463
[55d467e]464void MainWindow::slotCreateTerminal()
465{
[2e2ba31]466    QTermWidget* console = new QTermWidget(1,this);
[55d467e]467    QFont font = QApplication::font();
[5656dd1]468    font.setFamily("DejaVu Sans Mono");
[55d467e]469    font.setPointSize(12);
[dae65b7]470
[55d467e]471    console->setTerminalFont(font);
[2e2ba31]472    console->setFocusPolicy(Qt::StrongFocus);
[55d467e]473    console->setScrollBarPosition(QTermWidget::ScrollBarRight);
474
[b93c220]475    ++m_numberTerminal;
[55d467e]476
[2e2ba31]477    connect(console,SIGNAL(finished()),this,SLOT(slotDeleteTerminal()));
478
[6538925]479    QString name=tr("Term %1").arg(m_numberTerminal);
[b93c220]480    m_tabs->addTab(console,name);
[55d467e]481}
482
[2e2ba31]483void MainWindow::slotDeleteTerminal()
484{
[b93c220]485    QWidget *widget = qobject_cast<QWidget *>(sender());
486    Q_ASSERT(widget);
487    m_tabs->removeTab(m_tabs->indexOf(widget));
488    delete widget;
[2e2ba31]489}
490
[050d67a]491int MainWindow::readEnvironmentValues()
492{
493    // The return value
494    int ret=true;
495
496    // Get all environment variables
497    QStringList environmentlist=QProcess::systemEnvironment();
498    // This is the list of the important variables
499    QStringList variablelist=QString(ENVIRONMENT).split(",");
500
501    // This is an auxiliar variable
502    QStringList stringlist;
503
504    foreach (QString str,variablelist)
505    {
[dae65b7]506        // Look for the variable in the environment
[050d67a]507        stringlist=environmentlist.filter(str+"=");
508
509        if(stringlist.isEmpty())
510        {
[b93c220]511            m_env[str]="";
[050d67a]512            ret=false;
513        }
514        else
515        {
516            // Get the first element and get the value part
[b93c220]517            m_env[str]=(stringlist.first().split("="))[1];
[050d67a]518        }
519    }
520
521    return ret;
522}
[b93c220]523
[1b0403f]524// Write a string to the log file
525void MainWindow::write(QString s)
[b93c220]526{
[1b0403f]527    if(! s.endsWith("\n"))
[75617e0]528        s+="\n";
529    if(m_logstream)
530    {
531        *m_logstream<<CURRENT_TIME()<<": browser: "<<s;
532        m_logstream->flush();
533    }
[1b0403f]534}
535
536// Print and log a string
537void MainWindow::print(QString s)
538{
539    if(! s.endsWith("\n"))
540        s+="\n";
541    write(s);
[75617e0]542    if(m_output)
543        m_output->insertPlainText(s);
[b93c220]544}
[9d8d163]545
[1b0403f]546// Show message in status bar
[9d8d163]547void MainWindow::captureOutputForStatusBar(QString output)
548{
[1b0403f]549    // Modify the status bar
[75617e0]550    output=output.trimmed();
[1b0403f]551    // Get percentage (string starts with "[Number]")
[07ea3f8]552    QRegularExpression regexp(REGEXP_STRING);
553    QRegularExpressionMatch match = regexp.match(output);
554
555    if(match.hasMatch())
[75617e0]556    {
[07ea3f8]557        int pass=match.captured(1).toInt();
[75617e0]558        output.replace(regexp,"");
559        m_progressBar->setValue(pass);
560        m_progressBar->setFormat("%p%"+output);
561    }
[9d8d163]562}
563
[c646cde]564// Init status bar
[9d8d163]565void MainWindow::startProgressBar()
566{
567    QStatusBar* st=statusBar();
568    st->clearMessage();
[c646cde]569    st->addWidget(m_logo);
[099ac5d]570    st->addWidget(m_progressBar,90);
[c646cde]571    st->addWidget(m_speedInfo,5);
572    st->addWidget(m_clock,5);
[9d8d163]573    m_progressBar->show();
[099ac5d]574    m_clock->show();
[9d8d163]575    m_web->setEnabled(false);
576}
577
[1b0403f]578// Reset status bar
[9d8d163]579void MainWindow::finishProgressBar()
580{
[0dff9e1]581    m_progressBar->reset();
[9d8d163]582    m_web->setEnabled(true);
583}
[9d6a1e3]584
[c646cde]585
586// Returns communication speed
587QString MainWindow::readSpeed() {
588    if(m_env.contains("OGLOGFILE"))
589    {
590        QString infoFile=m_env["OGLOGFILE"].replace(".log", ".info.html");
[dae65b7]591        //QString command="grep -hoe \"[0-9]*Mb/s\" "+infoFile+" 2>/dev/null";
[c646cde]592        QProcess process;
[dae65b7]593        process.start("grep", QStringList({"-hoe", "[0-9]*Mb/s", infoFile}));
[c646cde]594        process.waitForFinished();
595        QString speed(process.readAllStandardOutput());
596        return speed.simplified();
597    }
598    else
599    {
600        return QString("");
601    }
602}
[75617e0]603
604// Show an error box with timeout
605void MainWindow::showErrorMessage(QString text)
606{
607    QMessageBox* msgBox=new QMessageBox();
608    msgBox->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint);
[f885166]609    msgBox->setWindowTitle("ERROR");
[75617e0]610    msgBox->setIcon(QMessageBox::Warning);
611    msgBox->setText(text);
612    msgBox->show();
613    QTimer::singleShot(5000, msgBox, SLOT(close()));
614}
Note: See TracBrowser for help on using the repository browser.