]> SALOME platform Git repositories - modules/gui.git/commitdiff
Salome HOME
0023564: [EDF] AsterStudy: introduce a feature to show popup notifications vsr/23564
authorvsr <vsr@opencascade.com>
Thu, 31 May 2018 10:31:43 +0000 (13:31 +0300)
committervsr <vsr@opencascade.com>
Thu, 31 May 2018 10:44:45 +0000 (13:44 +0300)
15 files changed:
src/CAM/CAM_Module.cxx
src/CAM/CAM_Module.h
src/LightApp/LightApp_Application.cxx
src/LightApp/resources/LightApp.xml
src/LightApp/resources/LightApp_msg_en.ts
src/LightApp/resources/LightApp_msg_fr.ts
src/LightApp/resources/LightApp_msg_ja.ts
src/Qtx/CMakeLists.txt
src/Qtx/QtxNotify.cxx [new file with mode: 0644]
src/Qtx/QtxNotify.h [new file with mode: 0644]
src/SALOME_PYQT/SalomePyQt/SalomePyQt.cxx
src/SALOME_PYQT/SalomePyQt/SalomePyQt.h
src/SALOME_PYQT/SalomePyQt/SalomePyQt.sip
src/STD/STD_Application.cxx
src/STD/STD_Application.h

index b886d8f5520bfb725c01f3ab87adb7815a2308ee..a5bcaf714e5925d17923871908e552d7d3f44455 100755 (executable)
@@ -327,6 +327,41 @@ void CAM_Module::putInfo( const QString& msg, const int msec )
     myInfo = msg;
 }
 
+/*!
+    \brief Shows the notifications with spectified text, title and automatic close timeout.
+    Notification will be automatically closed after specified timeout in msec. If
+    timeout is zero then automatic closing doesn't performed.
+    \param text - Notification text
+    \param title - Notification title
+    \param timeout - Notification close timeout in msec
+    \return notification identifier
+*/
+int CAM_Module::showNotification( const QString& message, const QString& title, int timeout )
+{
+  if ( application() )
+    application()->showNotification( message, title, timeout );
+}
+
+/*!
+    \brief Closes the notifications with spectified text.
+    \param text - Notification text
+*/
+void CAM_Module::hideNotification( const QString& message )
+{
+  if ( application() )
+    application()->hideNotification( message );
+}
+
+/*!
+    \brief Closes the notifications with spectified identifier.
+    \param text - Notification text
+*/
+void CAM_Module::hideNotification( int id )
+{
+  if ( application() )
+    application()->hideNotification( id );
+}
+
 /*!
   \brief Restore message info.
 
index bc96dc908617f9cc695a106239584c5e44a1d020..3cb43c1616f826df5d00b4d12278eb9418bb54b1 100755 (executable)
@@ -73,6 +73,10 @@ public:
 
   virtual void           putInfo( const QString&, const int = -1 );
 
+  int                    showNotification(const QString& message, const QString& title, int timeout = -1);
+  void                   hideNotification(const QString& message);
+  void                   hideNotification(int id);
+
   bool                   isActiveModule() const;
 
   virtual void           setMenuShown( const bool );
index 128df3e64ff5fde858c1a40663fb0ef3e3f8b286..9da7c829a9ca9027b547a20491800f3660221a43 100644 (file)
@@ -2399,6 +2399,12 @@ void LightApp_Application::createPreferences( LightApp_Preferences* pref )
   pref->addPreference( tr( "PREF_OPAQUE_RESIZE" ), lookGroup, LightApp_Preferences::Bool, "desktop", "opaque_resize" );
   // .... -> drop-down buttons 
   pref->addPreference( tr( "PREF_DROP_DOWN_BUTTONS" ), lookGroup, LightApp_Preferences::Bool, "viewers", "drop_down_buttons" );
+  // .... -> Notification timeout
+  int delay = pref->addPreference( tr( "PREF_NOTIFY_TIMEOUT" ), lookGroup, LightApp_Preferences::IntSpin, "notification", "timeout" );
+  pref->setItemProperty( "special", tr("PREF_NOTIFY_TIMEOUT_NONE"), delay );
+  pref->setItemProperty( "min", 0, delay );
+  pref->setItemProperty( "max", 100, delay );
+  pref->setItemProperty( "suffix", " sec", delay );
   // ... "Look and feel" group <<end>>
 
   // ... "Study properties" group <<start>>
index 9004e7b2ae8d9f207b1a16d1310085268c3a944e..7adc8b93d34977d98172729ff39bb7b867f72202 100644 (file)
   <section name="kernel_help" >
     <parameter name="Developer's Guide/KERNEL module" value="${KERNEL_ROOT_DIR}/share/doc/salome/tui/KERNEL/index.html"/>
   </section>
+  <section name="notification" >
+    <parameter name="timeout" value="10"/>
+    <parameter name="animation" value="0"/>
+    <parameter name="size" value="300"/>
+  </section>
   <!--Salome shortcut settings-->
   <section name="shortcuts_settings">
     <parameter name="general_sections" value="General;Viewers"/>
index 9efc62202fae5beffc86b6a13fb5054168fd7fc2..8752d4c0f40fded21475355b6c32dab4a0086e46 100644 (file)
@@ -528,7 +528,7 @@ The changes will be applied on the next application session.</translation>
         <source>NEW_WINDOW_6</source>
         <translation>ParaVie&amp;w view</translation>
     </message>
-       <message>
+    <message>
         <source>NEW_WINDOW_7</source>
         <translation>P&amp;ython view</translation>
     </message>
@@ -648,6 +648,14 @@ The changes will be applied on the next application session.</translation>
         <source>PREF_DROP_DOWN_BUTTONS</source>
         <translation>Drop-down buttons in toolbars for action groups</translation>
     </message>
+    <message>
+        <source>PREF_NOTIFY_TIMEOUT</source>
+        <translation>Notifications auto-hide timeout</translation>
+    </message>
+    <message>
+        <source>PREF_NOTIFY_TIMEOUT_NONE</source>
+        <translation>None</translation>
+    </message>
     <message>
         <source>PREF_GROUP_COMMON</source>
         <translation>Common</translation>
index 4a3b4610fe1426a217919cafada9f331c8dbe716..9a07d916eb42955cae505cf1d070cdbc5e238e89 100755 (executable)
@@ -46,6 +46,18 @@ CEA/DEN, CEDRAT, EDF R&amp;D, LEG, PRINCIPIA R&amp;D, BUREAU VERITAS</translatio
         <source>ABOUT_VERSION</source>
         <translation>Version %1</translation>
     </message>
+    <message>
+        <source>SALOME_SITE</source>
+        <translation type="unfinished">SALOME Website</translation>
+    </message>
+    <message>
+        <source>SALOME_FORUM</source>
+        <translation type="unfinished">SALOME Forum</translation>
+    </message>
+    <message>
+        <source>SALOME_VIDEO_TUTORIALS</source>
+        <translation type="unfinished">Video Tutorials</translation>
+    </message>
     <message>
         <source>ENTRY_COLUMN</source>
         <translation>Entrée</translation>
@@ -636,6 +648,14 @@ Les modifications seront appliquées à la prochaine session.</translation>
         <source>PREF_DROP_DOWN_BUTTONS</source>
         <translation>Boutons alignés dans la barre</translation>
     </message>
+    <message>
+        <source>PREF_NOTIFY_TIMEOUT</source>
+        <translation type="unfinished">Notifications auto-hide timeout</translation>
+    </message>
+    <message>
+        <source>PREF_NOTIFY_TIMEOUT_NONE</source>
+        <translation type="unfinished">None</translation>
+    </message>
     <message>
         <source>PREF_GROUP_COMMON</source>
         <translation>Commun</translation>
index 632c65c917dc4f5a5e8c95474eb7fb850eb815a6..6ba9e65b43b714278da8bc829c938a946f7e149e 100644 (file)
@@ -46,6 +46,18 @@ CEA/DEN, CEDRAT, EDF R&amp;D, LEG, PRINCIPIA R&amp;D, BUREAU VERITAS</translatio
       <source>ABOUT_VERSION</source>
       <translation>Version %1</translation>
     </message>
+    <message>
+        <source>SALOME_SITE</source>
+        <translation type="unfinished">SALOME Website</translation>
+    </message>
+    <message>
+        <source>SALOME_FORUM</source>
+        <translation type="unfinished">SALOME Forum</translation>
+    </message>
+    <message>
+        <source>SALOME_VIDEO_TUTORIALS</source>
+        <translation type="unfinished">Video Tutorials</translation>
+    </message>
     <message>
       <source>ENTRY_COLUMN</source>
       <translation>エントリ</translation>
@@ -636,6 +648,14 @@ Pythonファイルは、文字、数字、アンダースコアが含まれて
       <source>PREF_DROP_DOWN_BUTTONS</source>
       <translation>バーでのボタンの配置</translation>
     </message>
+    <message>
+      <source>PREF_NOTIFY_TIMEOUT</source>
+      <translation type="unfinished">Notifications auto-hide timeout</translation>
+    </message>
+    <message>
+      <source>PREF_NOTIFY_TIMEOUT_NONE</source>
+      <translation type="unfinished">None</translation>
+    </message>
     <message>
       <source>PREF_GROUP_COMMON</source>
       <translation>共通</translation>
index ad1337ffc18e4aa47753c5d305fe0bf4e354330e..bca0f0dc98f67ca1e50b9ef7ceda8ae79bcc59f5 100755 (executable)
@@ -61,6 +61,7 @@ SET(_moc_HEADERS
   QtxMainWindow.h
   QtxMenu.h
   QtxMultiAction.h
+  QtxNotify.h
   QtxPagePrefMgr.h
   QtxPathDialog.h
   QtxPathEdit.h
@@ -152,6 +153,7 @@ SET(_other_SOURCES
   QtxMainWindow.cxx
   QtxMenu.cxx
   QtxMultiAction.cxx
+  QtxNotify.cxx
   QtxPagePrefMgr.cxx
   QtxPathDialog.cxx
   QtxPathEdit.cxx
diff --git a/src/Qtx/QtxNotify.cxx b/src/Qtx/QtxNotify.cxx
new file mode 100644 (file)
index 0000000..c958905
--- /dev/null
@@ -0,0 +1,945 @@
+// Copyright (C) 2007-2018  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#include "QtxNotify.h"
+
+#include <QTimer>
+#include <QPainter>
+#include <QMouseEvent>
+#include <QApplication>
+#include <QTextDocument>
+#include <QDesktopWidget>
+#include <QSharedPointer>
+#include <QPropertyAnimation>
+#include <QParallelAnimationGroup>
+
+/*!
+    \brief QtxNotify::NotifyWidget
+    Class represented notification widget
+*/
+
+class QtxNotify::NotifyWidget : public QWidget
+{
+    typedef QSharedPointer<QTextDocument> TextDocument;
+
+public:
+    NotifyWidget(QtxNotify*, const QString& title,
+                 const QString& text, const int timeout, QWidget* parent = 0);
+    virtual ~NotifyWidget();
+
+    QtxNotify*             notifyMgr() const;
+
+    int                    id() const;
+    QString                text() const;
+    QString                title() const;
+    int                    timeout() const;
+
+    void                   setId(const int);
+    void                   setText(const QString&);
+    void                   setTitle(const QString&);
+    void                   setTimeout(const int);
+
+    virtual QSize          sizeHint() const;
+    virtual QSize          minimumSizeHint() const;
+
+protected:
+    virtual void           showEvent(QShowEvent*);
+    virtual void           paintEvent(QPaintEvent*);
+    virtual void           mouseMoveEvent(QMouseEvent*);
+    virtual void           mousePressEvent(QMouseEvent*);
+    virtual void           mouseReleaseEvent(QMouseEvent*);
+
+private:
+    int                    frameWidth() const;
+    int                    notificationWidth() const;
+
+    QRect                  textRect() const;
+    QRect                  titleRect() const;
+    QRect                  closeRect() const;
+    TextDocument           textDocument() const;
+
+    void                   onTimeout();
+
+private:
+    int                    myId;
+    QString                myText;
+    QString                myTitle;
+    QTimer*                myTimer;
+    QtxNotify*             myNotifyMgr;
+
+    bool                   myIsClosePressed;
+};
+
+/*!
+    \brief Constructor [private]
+*/
+QtxNotify::NotifyWidget::NotifyWidget(QtxNotify* mgr, const QString& title, const QString& text,
+                                      const int timeout, QWidget* parent)
+    : QWidget(parent, (parent ? Qt::Widget : Qt::Tool) | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint),
+      myTitle(title),
+      myText(text),
+      myTimer(new QTimer(this)),
+      myNotifyMgr(mgr),
+      myIsClosePressed(false)
+{
+    myTimer->setSingleShot(true);
+
+    connect(myTimer, &QTimer::timeout, this, &QtxNotify::NotifyWidget::onTimeout);
+
+    setTimeout(timeout);
+    setMouseTracking(true);
+}
+
+/*!
+    \brief Destructor
+*/
+QtxNotify::NotifyWidget::~NotifyWidget()
+{
+}
+
+/*!
+    \brief Gets the notification manager.
+    \return notification manager instance
+*/
+QtxNotify* QtxNotify::NotifyWidget::notifyMgr() const
+{
+    return myNotifyMgr;
+}
+
+/*!
+    \brief Gets the notification identifier.
+    \return notification identifier
+*/
+int QtxNotify::NotifyWidget::id() const
+{
+    return myId;
+}
+
+/*!
+    \brief Gets the notification text.
+    \return notification text string
+*/
+QString QtxNotify::NotifyWidget::text() const
+{
+    return myText;
+}
+
+/*!
+    \brief Gets the notification title.
+    \return notification title string
+*/
+QString QtxNotify::NotifyWidget::title() const
+{
+    return myTitle;
+}
+
+/*!
+    \brief Gets the notification timeout.
+    \return notification timeout
+*/
+int QtxNotify::NotifyWidget::timeout() const
+{
+    return myTimer->interval();
+}
+
+/*!
+    \brief Sets the notification timeout.
+    \param id - notification identifier
+*/
+void QtxNotify::NotifyWidget::setId(const int id)
+{
+    myId = id;
+}
+
+/*!
+    \brief Sets the notification text.
+    \param text - notification text string
+*/
+void QtxNotify::NotifyWidget::setText(const QString& text)
+{
+    myText = text;
+    updateGeometry();
+    update();
+}
+
+/*!
+    \brief Sets the notification title.
+    \param title - notification title string
+*/
+void QtxNotify::NotifyWidget::setTitle(const QString& title)
+{
+    myTitle = title;
+    update();
+}
+
+/*!
+    \brief Sets the notification timeout.
+    \param timeout - notification timeout
+*/
+void QtxNotify::NotifyWidget::setTimeout(const int timeout)
+{
+    if (myTimer->isActive())
+        myTimer->stop();
+    myTimer->setInterval(timeout);
+
+    if (isVisible() && myTimer->interval() > 0)
+        myTimer->start();
+}
+
+/*!
+    \brief Gets the notification widget size hint.
+    \return size hint
+*/
+QSize QtxNotify::NotifyWidget::sizeHint() const
+{
+    return minimumSizeHint();
+}
+
+/*!
+    \brief Gets the notification widget minimum size hint.
+    \return minimum size hint
+*/
+QSize QtxNotify::NotifyWidget::minimumSizeHint() const
+{
+    int frame = frameWidth();
+    int width = notificationWidth();
+    TextDocument doc = textDocument();
+    int height = (int)doc->size().height() + 2 * frame;
+
+    height += fontMetrics().height() + 2 * frame;
+
+    return QSize(width, height);
+}
+
+void QtxNotify::NotifyWidget::showEvent(QShowEvent* e)
+{
+  QWidget::showEvent(e);
+
+  if (!myTimer->isActive() && myTimer->interval() > 0)
+    myTimer->start();
+}
+
+/*!
+    \brief Reimplemented for notification drawing.
+*/
+void QtxNotify::NotifyWidget::paintEvent(QPaintEvent*)
+{
+    QPainter painter(this);
+
+    QRect clsRect = closeRect();
+    QRect ttlRect = titleRect();
+    QRect txtRect = textRect();
+
+    // Fills background and frame
+    painter.setRenderHint(QPainter::TextAntialiasing);
+    painter.fillRect(QRect(QPoint(0,0), size()), Qt::darkGray);
+    painter.fillRect(txtRect, Qt::white);
+
+    // Draw title
+    painter.save();
+
+    painter.setPen(Qt::white);
+    QFont fnt = font();
+    fnt.setBold(true);
+    painter.setFont(fnt);
+    ttlRect.setRight(clsRect.left());
+
+    QString titleText = title().trimmed();
+    if (QFontMetrics(painter.font()).width(titleText) > ttlRect.width())
+        titleText = QFontMetrics(painter.font()).elidedText(titleText, Qt::ElideRight, ttlRect.width() - 5);
+    painter.drawText(ttlRect.adjusted(2, 0, 0, 0), Qt::AlignVCenter, titleText);
+
+    painter.restore();
+
+    // Draw close button
+    painter.save();
+
+    if (myIsClosePressed && clsRect.contains(mapFromGlobal(QCursor::pos())))
+    {
+        painter.fillRect(clsRect.adjusted(0, 0, -1, -1), Qt::gray);
+        clsRect = clsRect.adjusted(1, 1, 0, 0);
+    }
+    else
+    {
+        painter.fillRect(clsRect.adjusted(1, 1, 0, 0), Qt::lightGray);
+        clsRect = clsRect.adjusted(0, 0, -1, -1);
+    }
+    painter.fillRect(clsRect, Qt::red);
+
+    int m = 2;
+    painter.setPen(Qt::white);
+    QRect rect = clsRect.adjusted(m, m, -m, -m);
+    painter.drawLine(rect.topLeft(), rect.bottomRight());
+    painter.drawLine(rect.topRight(), rect.bottomLeft());
+
+    painter.restore();
+
+    // Draw text
+    painter.save();
+
+    painter.setPen(Qt::black);
+    TextDocument doc = textDocument();
+    painter.translate(txtRect.topLeft());
+    doc->drawContents(&painter, QRectF(QPointF(0, 0), txtRect.size()));
+
+    painter.restore();
+
+    painter.end();
+}
+
+/*!
+    \brief Reimplemented for handling close button.
+*/
+void QtxNotify::NotifyWidget::mouseMoveEvent(QMouseEvent*)
+{
+    if (myIsClosePressed)
+        update();
+}
+
+/*!
+    \brief Reimplemented for handling close button.
+*/
+void QtxNotify::NotifyWidget::mousePressEvent(QMouseEvent* e)
+{
+    if (e->button() == Qt::LeftButton && closeRect().contains(e->pos()))
+    {
+        myIsClosePressed = true;
+        update();
+    }
+}
+
+/*!
+    \brief Reimplemented for handling close button.
+*/
+void QtxNotify::NotifyWidget::mouseReleaseEvent(QMouseEvent* e)
+{
+    if (e->button() == Qt::LeftButton)
+    {
+        if (myIsClosePressed && closeRect().contains(e->pos()))
+        {
+            notifyMgr()->hideNotification(id());
+        }
+        myIsClosePressed = false;
+        update();
+    }
+}
+
+/*!
+    \brief Gets the notification frame with
+    \return Frame width in pixels
+*/
+int QtxNotify::NotifyWidget::frameWidth() const
+{
+    return 2;
+}
+
+/*!
+    \brief Gets the notification window with
+    \return width in pixels
+*/
+int QtxNotify::NotifyWidget::notificationWidth() const
+{
+    return notifyMgr()->notificationWidth();
+}
+
+/*!
+    \brief Gets the text document with actual text and size.
+    \return text document instance
+*/
+QtxNotify::NotifyWidget::TextDocument QtxNotify::NotifyWidget::textDocument() const
+{
+    TextDocument doc(new QTextDocument());
+    if (Qt::mightBeRichText(text()))
+        doc->setHtml(text());
+    else
+        doc->setPlainText(text());
+    doc->setTextWidth(notificationWidth() - 2 * frameWidth());
+    return doc;
+}
+
+/*!
+    \brief Gets the notification message text rectangle.
+    \return text rectangle
+*/
+QRect QtxNotify::NotifyWidget::textRect() const
+{
+    int frame = frameWidth();
+    return QRect(frame, 3 * frame + fontMetrics().height(),
+                 width() - 2 * frame, height() - 4 * frame - fontMetrics().height());
+}
+
+/*!
+    \brief Gets the notification title rectangle
+    \return title rectangle
+*/
+QRect QtxNotify::NotifyWidget::titleRect() const
+{
+    int frame = frameWidth();
+    return QRect(frame, frame, width() - 2 * frame, fontMetrics().height() + 2 * frame);
+}
+
+/*!
+    \brief Gets the notification close button rectangle.
+    \return close rectangle
+*/
+QRect QtxNotify::NotifyWidget::closeRect() const
+{
+    int frame = frameWidth();
+    int size = fontMetrics().height();
+    return QRect(width() - 2 * frame - size, 2 * frame, size, size);
+}
+
+/*!
+    \brief Invoked when notification close timeout and hide the notification.
+*/
+void QtxNotify::NotifyWidget::onTimeout()
+{
+    notifyMgr()->hideNotification(id());
+}
+
+/*!
+    \brief QtxNotify
+    Class that manages all notification instances. Performs show, hide, placing, etc
+*/
+
+/*!
+    \brief Constructor.
+*/
+QtxNotify::QtxNotify(QObject* parent)
+    : QObject(parent),
+    mySize(250),
+    myWindow(0),
+    myPlacement(TopToBottom),
+    myAlignment(Qt::AlignRight|Qt::AlignTop),
+    myAnimTime(0),
+    myAnimBlock(false)
+{
+    myArrangeTimer = new QTimer(this);
+    myArrangeTimer->setInterval(0);
+    myArrangeTimer->setSingleShot(true);
+    connect(myArrangeTimer, SIGNAL(timeout()), this, SLOT(onArrangeTimeout()));
+
+    QWidget* window = 0;
+    QWidgetList windows = QApplication::topLevelWidgets();
+    for ( QWidgetList::iterator it = windows.begin(); it != windows.end() && !window; ++it )
+    {
+        QWidget* win = *it;
+        if (win->isVisible() &&
+            (win->windowType() == Qt::Widget || win->windowType() == Qt::Window))
+            window = win;
+    }
+
+    setWindow(window ? window : QApplication::desktop());
+}
+
+/*!
+    \brief Constructor.
+*/
+QtxNotify::QtxNotify(QWidget* win, QObject* parent)
+    : QObject(parent),
+    mySize(250),
+    myWindow(0),
+    myPlacement(TopToBottom),
+    myAlignment(Qt::AlignRight|Qt::AlignTop),
+    myAnimTime(0),
+    myAnimBlock(false)
+{
+    myArrangeTimer = new QTimer(this);
+    myArrangeTimer->setInterval(0);
+    myArrangeTimer->setSingleShot(true);
+    connect(myArrangeTimer, SIGNAL(timeout()), this, SLOT(onArrangeTimeout()));
+
+    setWindow(win);
+}
+
+/*!
+    \brief Destructor.
+*/
+QtxNotify::~QtxNotify()
+{
+}
+
+/*!
+    \brief Shows the notifications with spectified text, title and automatic close timeout.
+    Notification will be automatically closed after specified timeout in msec. If
+    timeout is zero then automatic closing doesn't performed.
+    \param text - Notification text
+    \param title - Notification title
+    \param timeout - Notification close timeout in msec
+    \return notification identifier
+*/
+int QtxNotify::showNotification(const QString& text, const QString& title, int timeout)
+{
+    QtxNotify::NotifyWidget* notify = notification(text);
+    if (!notify)
+    {
+        notify = new QtxNotify::NotifyWidget(this, title, text, timeout, window());
+        notify->setId(generateId());
+    }
+    else
+    {
+        myNotifications.removeAll(notify);
+        notify->setTimeout(timeout);
+        notify->setTitle(title);
+        notify->hide();
+    }
+
+    myNotifications.append(notify);
+    triggerArrange();
+
+    return notify->id();
+}
+
+/*!
+    \brief Closes the notifications with spectified text.
+    \param text - Notification text
+*/
+void QtxNotify::hideNotification(const QString& text)
+{
+    removeNotification(notification(text));
+}
+
+/*!
+    \brief Closes the notifications with spectified identifier.
+    \param text - Notification identifier
+*/
+void QtxNotify::hideNotification(const int id)
+{
+    removeNotification(notification(id));
+}
+
+/*!
+    \brief Gets the reference widget for all notifications.
+    \return reference widget
+*/
+QWidget* QtxNotify::window() const
+{
+    return myWindow;
+}
+
+/*!
+    \brief Sets the reference widget for all notifications.
+    \param win - reference widget
+*/
+void QtxNotify::setWindow(QWidget* window)
+{
+    if (myWindow != window)
+    {
+        if (myWindow)
+            myWindow->removeEventFilter(this);
+        myWindow = window;
+        if (myWindow)
+            myWindow->installEventFilter(this);
+        updateArrangement();
+    }
+}
+
+/*!
+    \brief Gets the animation time in msec for notification modifications.
+    \return animation time
+*/
+int QtxNotify::animationTime() const
+{
+    return myAnimTime;
+}
+
+/*!
+    \brief Sets the animation time in msec for notification modifications.
+    If animation time is zero then animation is disabled.
+    \param time - animation time
+*/
+void QtxNotify::setAnimationTime(const int time)
+{
+    myAnimTime = time;
+}
+
+/*!
+    \brief Gets the notification placement policy.
+    \return notification placement policy
+*/
+QtxNotify::PlacementPolicy QtxNotify::placementPolicy() const
+{
+    return myPlacement;
+}
+
+/*!
+    \brief Sets the notification placement policy.
+    \param placement - notification placement policy
+*/
+void QtxNotify::setPlacementPolicy(const QtxNotify::PlacementPolicy& placement)
+{
+    if (myPlacement != placement)
+    {
+        myPlacement = placement;
+        updateArrangement();
+    }
+}
+
+/*!
+    \brief Gets the notification placement base point alignment.
+    \return alignment flags
+*/
+int QtxNotify::alignment() const
+{
+    return myAlignment;
+}
+
+/*!
+    \brief Sets the notification placement base point alignment.
+    \param falgs - alignment flags
+*/
+void QtxNotify::setAlignment(const int flags)
+{
+    if (myAlignment != flags)
+    {
+        myAlignment = flags;
+        updateArrangement();
+    }
+}
+
+/*!
+    \brief Reimplemented for tracking reference widget size changing and
+    update notification geometries.
+    \param o - handled object
+    \param e - handled event
+*/
+bool QtxNotify::eventFilter(QObject* o, QEvent* e)
+{
+    if (e->type() == QEvent::Resize && o == window())
+    {
+        updateArrangement();
+    }
+    return QObject::eventFilter(o, e);
+}
+
+/*!
+    \brief Gets the notification width size of each notification. If size value more than 1
+           then it will be interpreted as absolute width in pixels. If size value in range
+           between 0 and 1 then notification width will be calculated as relative part of
+           reference window width.
+    \return notification size
+*/
+double QtxNotify::notificationSize() const
+{
+    return mySize;
+}
+
+/*!
+    \brief Sets the notification width size of each notification.
+    \param size - notification size
+*/
+void QtxNotify::setNotificationSize(const double size)
+{
+    if (mySize != size)
+    {
+        mySize = size;
+        updateArrangement();
+    }
+}
+
+/*!
+    \brief Performs the update of all notification geometries.
+    If parameter anim is true then arrangment will be animated otherwise not.
+    \param anim - use animation
+*/
+void QtxNotify::arrangeNotifications(bool anim)
+{
+    if (myNotifications.isEmpty())
+        return;
+
+    QWidget* ref = window() ? window() : QApplication::desktop();
+    QPoint refPoint = referencePoint();
+    if (myNotifications.first()->isWindow())
+        refPoint = ref->mapToGlobal(refPoint);
+
+    int space = 10;
+    NotifyList notifications;
+    bool reverse = placementPolicy() == QtxNotify::BottomToTop;
+    if (alignment() & Qt::AlignBottom)
+        reverse = !reverse;
+
+    if (reverse)
+    {
+        for ( NotifyList::reverse_iterator it = myNotifications.rbegin(); it != myNotifications.rend(); ++it )
+            notifications.append(*it);
+    }
+    else
+    {
+        for ( NotifyList::iterator it = myNotifications.begin(); it != myNotifications.end(); ++it )
+            notifications.append(*it);
+    }
+
+    int sign = alignment() & Qt::AlignBottom ? -1 : 1;
+    QPoint pos = refPoint;
+    QMap<QtxNotify::NotifyWidget*, QRect> geoms;
+    for ( NotifyList::iterator it = notifications.begin(); it != notifications.end(); ++it )
+    {
+        QtxNotify::NotifyWidget* notify = *it;
+        QSize size = notify->sizeHint();
+        geoms.insert(notify, QRect(QPoint(pos.x(), pos.y() - (sign < 0 ? size.height() : 0)), size));
+        pos = QPoint(pos.x(), pos.y() + sign * ( size.height() + space ));
+    }
+
+    QParallelAnimationGroup* animGroup = 0;
+    if (isAnimated() && anim)
+        animGroup = new QParallelAnimationGroup();
+
+    for ( NotifyList::iterator iter = notifications.begin(); iter != notifications.end(); ++iter )
+    {
+        QtxNotify::NotifyWidget* notify = *iter;
+        QRect geom = geoms[notify];
+        if (notify->parentWidget())
+            geom = QRect(notify->parentWidget()->mapFromGlobal(geom.topLeft()), geom.size());
+
+        bool isvis = notify->isVisible();
+
+        if (animGroup)
+        {
+            QPropertyAnimation* animation = new QPropertyAnimation(notify, "geometry");
+            animation->setDuration(animationTime());
+            animGroup->addAnimation(animation);
+            if (isvis)
+            {
+                animation->setStartValue(notify->geometry());
+                animation->setEndValue(geom);
+            }
+            else
+            {
+                notify->show();
+                animation->setStartValue(QRect(QPoint(geom.center().x(), geom.top()), QSize(0, geom.height())));
+                animation->setEndValue(geom);
+            }
+        }
+        else
+        {
+            notify->setGeometry(geom);
+            notify->show();
+        }
+    }
+    if (animGroup)
+        startAnimation(animGroup);
+}
+
+QPoint QtxNotify::referencePoint() const
+{
+    int margin = 5;
+    QWidget* ref = window() ? window() : QApplication::desktop();
+
+    QPoint refPoint;
+    int notifywidth = notificationWidth();
+    int align = alignment() > 0 ? alignment() : Qt::AlignLeft | Qt::AlignTop;
+
+    if (align & Qt::AlignLeft)
+        refPoint.setX(margin);
+    else if (align & Qt::AlignRight)
+        refPoint.setX(ref->width() - notifywidth - margin);
+    else if (align & Qt::AlignHCenter)
+        refPoint.setX((ref->width() - notifywidth) / 2);
+
+    if (align & Qt::AlignTop)
+        refPoint.setY(margin);
+    else if (align & Qt::AlignBottom)
+        refPoint.setY(ref->height() - margin);
+    else if (align & Qt::AlignVCenter)
+        refPoint.setY(ref->height() / 2);
+
+    return ref->mapToGlobal(refPoint);
+}
+
+/*!
+    \brief Gets the notification with specified identifier.
+    \param id - notification identifier
+    \return notification instance
+*/
+QtxNotify::NotifyWidget* QtxNotify::notification(const int id)
+{
+    QtxNotify::NotifyWidget* notify = 0;
+    for (NotifyList::const_iterator it = myNotifications.begin(); it != myNotifications.end() && !notify; ++it)
+    {
+        if ((*it)->id() == id)
+            notify = *it;
+    }
+    return notify;
+}
+
+/*!
+    \brief Gets the notification with specified text.
+    \param text - notification text
+    \return notification instance
+*/
+QtxNotify::NotifyWidget* QtxNotify::notification(const QString& text)
+{
+    QtxNotify::NotifyWidget* notify = 0;
+    for (NotifyList::const_iterator it = myNotifications.begin(); it != myNotifications.end() && !notify; ++it)
+    {
+        if ((*it)->text() == text)
+            notify = *it;
+    }
+    return notify;
+}
+
+/*!
+    \brief Removes the specified notification.
+    \param notify - notification instance
+*/
+void QtxNotify::removeNotification(QtxNotify::NotifyWidget* notify)
+{
+    if (!notify)
+        return;
+
+    myNotifications.removeAll(notify);
+    notify->setTimeout(0);
+
+    if (isAnimated()) {
+        QPropertyAnimation* animation = new QPropertyAnimation(notify, "geometry");
+        animation->setDuration(animationTime());
+        animation->setStartValue(notify->geometry());
+        animation->setEndValue(QRect(QPoint(notify->geometry().center().x(), notify->geometry().top()),
+                                     QSize(0, notify->geometry().height())));
+
+        connect(animation, SIGNAL(finished()), notify, SLOT(hide()));
+        connect(animation, SIGNAL(finished()), notify, SLOT(deleteLater()));
+        connect(animation, SIGNAL(finished()), this, SLOT(onArrangeTimeout()));
+        startAnimation(animation);
+    }
+    else
+    {
+        notify->hide();
+        notify->deleteLater();
+        arrangeNotifications();
+    }
+}
+
+/*!
+    \brief Generates the new free notification identifier.
+    \return generated identifier
+*/
+int QtxNotify::generateId() const
+{
+    QMap<int, bool> map;
+    for (NotifyList::const_iterator it = myNotifications.begin(); it != myNotifications.end(); ++it)
+        map.insert((*it)->id(), true);
+
+    int id = 0;
+    while (map.contains(id))
+        id++;
+    return id;
+}
+
+/*!
+    \brief Gets the notification window with
+    \return width in pixels
+*/
+int QtxNotify::notificationWidth() const
+{
+    QWidget* refWin = window();
+    double size = notificationSize();
+    int width = (int)( size > 1 ? size : size * refWin->width() );
+    width = qMin(width, refWin->width() - 10);
+    return width;
+}
+
+/*!
+    \brief Schedule delayed notification arrangement.
+*/
+void QtxNotify::triggerArrange()
+{
+    if (myArrangeTimer->isActive())
+        myArrangeTimer->stop();
+    myArrangeTimer->start();
+}
+
+/*!
+    \brief Gets the animation using state.
+    If it's true then animation will be used during notification modifcations.
+    \return animation using state
+*/
+bool QtxNotify::isAnimated() const
+{
+    return myAnimTime > 0;
+}
+
+/*!
+    \brief Gets the active animation state. If there is exist active animation then return true otherwise false.
+    \return active animation state
+*/
+bool QtxNotify::hasAcitveAnimation() const
+{
+    bool has = false;
+    for (AnimationList::const_iterator it = myAnimations.begin(); it != myAnimations.end() && !has; ++it)
+        has = (*it)->state() == QAbstractAnimation::Running;
+    return has;
+}
+
+/*!
+    \brief Starts the given animation.
+    \param animation - animation instance
+*/
+void QtxNotify::startAnimation(QAbstractAnimation* animation)
+{
+    myAnimations.append(animation);
+    connect(animation, SIGNAL(destroyed(QObject*)), this, SLOT(onAnimationDestroyed(QObject*)));
+
+    animation->start(QAbstractAnimation::DeleteWhenStopped);
+}
+
+/*!
+    \brief Stops the given animation.
+    \param animation - animation instance
+*/
+void QtxNotify::stopAnimation(QAbstractAnimation* animation)
+{
+    animation->stop();
+    animation->deleteLater();
+}
+
+/*!
+    \brief Invoked when animation is destroyed. Removes the destroyed animation reference from list.
+    \param obj - destroyed animation reference
+*/
+void QtxNotify::onAnimationDestroyed(QObject* obj)
+{
+    myAnimations.removeAll((QAbstractAnimation*)obj);
+}
+
+/*!
+    \brief Performs the scheduled delayed notification arrangment.
+*/
+void QtxNotify::onArrangeTimeout()
+{
+    if (hasAcitveAnimation())
+        triggerArrange();
+    else
+    {
+        arrangeNotifications(!myAnimBlock);
+        myAnimBlock = false;
+    }
+}
+
+/*!
+    \brief Performs the notification arrangment with disabled animation.
+*/
+void QtxNotify::updateArrangement()
+{
+    myAnimBlock = true;
+    triggerArrange();
+}
diff --git a/src/Qtx/QtxNotify.h b/src/Qtx/QtxNotify.h
new file mode 100644 (file)
index 0000000..f5647c7
--- /dev/null
@@ -0,0 +1,117 @@
+// Copyright (C) 2007-2018  CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef QTXNOTIFY_H
+#define QTXNOTIFY_H
+
+#include <QWidget>
+
+#include <QList>
+#include <QAbstractAnimation>
+
+class QTimer;
+
+class QtxNotify : public QObject
+{
+    Q_OBJECT
+
+    class NotifyWidget;
+
+public:
+    typedef enum {
+        TopToBottom,
+        BottomToTop
+    } PlacementPolicy;
+
+    Q_ENUM(PlacementPolicy)
+
+public:
+    QtxNotify(QObject* = 0);
+    QtxNotify(QWidget*, QObject* = 0);
+    virtual ~QtxNotify();
+
+    int             showNotification(const QString&, const QString&, int timeout = -1);
+    void            hideNotification(const QString& = QString());
+    void            hideNotification(const int);
+
+    QWidget*        window() const;
+    void            setWindow(QWidget* window);
+
+    double          notificationSize() const;
+    void            setNotificationSize(const double);
+
+    int             animationTime() const;
+    void            setAnimationTime(const int);
+
+    PlacementPolicy placementPolicy() const;
+    void            setPlacementPolicy(const PlacementPolicy&);
+
+    int             alignment() const;
+    void            setAlignment(const int);
+
+    virtual bool    eventFilter(QObject*, QEvent*);
+
+private Q_SLOTS:
+    void            onArrangeTimeout();
+    void            onAnimationDestroyed(QObject*);
+
+private:
+    void            triggerArrange();
+    void            updateArrangement();
+    void            arrangeNotifications(bool = true);
+
+    NotifyWidget*   notification(const int);
+    NotifyWidget*   notification(const QString&);
+    void            removeNotification(NotifyWidget*);
+
+    int             generateId() const;
+
+    bool            isAnimated() const;
+
+    bool            hasAcitveAnimation() const;
+    void            startAnimation(QAbstractAnimation*);
+    void            stopAnimation(QAbstractAnimation*);
+
+    QPoint          referencePoint() const;
+    int             notificationWidth() const;
+
+private:
+    typedef QList<QtxNotify::NotifyWidget*> NotifyList;
+    typedef QList<QAbstractAnimation*>      AnimationList;
+
+private:
+    double          mySize;
+    QWidget*        myWindow;
+    PlacementPolicy myPlacement;
+    int             myAlignment;
+    QTimer*         myArrangeTimer;
+
+    int             myAnimTime;
+    bool            myAnimBlock;
+    AnimationList   myAnimations;
+
+    NotifyList      myNotifications;
+
+    friend class QtxNotify::NotifyWidget;
+};
+
+#endif // QTXNOTIFY_H
index 7b0220096e5b1c0d8b92b33abfc9c8ca77e3c187..d69a60b1b2284c06db0b87c5db6c99496327c8f8 100644 (file)
@@ -750,6 +750,93 @@ void SalomePyQt::putInfo( const QString& msg, const int sec )
   ProcessVoidEvent( new TPutInfoEvent( msg, sec ) );
 }
 
+/*!
+  \fn int SalomePyQt::showNotification( const QString& msg, const QString& title, const int sec );
+  \brief Show notification in the application's desktop window.
+
+  Optional third delay parameter (\a sec) can be used to specify
+  time of the notification diplaying in seconds. If this parameter is less
+  or equal to zero, the permanent notification will be put.
+
+  Notification can be forcibly hidden via hideNotification() method.
+
+  \param msg message text 
+  \param title title text 
+  \param sec notification displaying time in seconds
+  \return unique ID of the notification (can be used to hide notification)
+  \sa hideNotification()
+*/
+
+class TShowNotifyEvent: public SALOME_Event
+{
+  QString myMsg;
+  QString myTitle;
+  int     mySecs;
+
+public:
+  typedef int TResult;
+  TResult myResult;
+
+public:
+  TShowNotifyEvent( const QString& msg, const QString& title, const int sec = -1 ) : myMsg( msg ), myTitle( title), mySecs( sec ), myResult( -1 ) {}
+  virtual void Execute()
+  {
+    if ( LightApp_Application* anApp = getApplication() ) {
+      myResult = anApp->showNotification( myMsg, myTitle, mySecs * 1000 );
+    }
+  }
+};
+
+int SalomePyQt::showNotification( const QString& msg, const QString& title, const int sec )
+{
+  return ProcessEvent( new TShowNotifyEvent( msg, title, sec ) );
+}
+
+/*!
+  \fn void SalomePyQt::hideNotification( const QString& msg );
+  \brief Remove notification with given message text from the application's desktop.
+
+  \param msg message text
+  \sa showNotification()
+*/
+
+/*!
+  \fn void SalomePyQt::hideNotification( const int id );
+  \brief Remove notification with given \a id from the application's desktop.
+
+  \param id notification id
+  \sa showNotification()
+*/
+
+class THideNotifyEvent: public SALOME_Event
+{
+  int     myId;
+  QString myMsg;
+
+public:
+  THideNotifyEvent( const QString& msg ) : myId( -1 ), myMsg( msg ) {}
+  THideNotifyEvent( const int id ) : myId( id ) {}
+  virtual void Execute()
+  {
+    if ( LightApp_Application* anApp = getApplication() ) {
+      if ( myId >= 0 )
+       anApp->hideNotification( myId );
+      else
+       anApp->hideNotification( myMsg );
+    }
+  }
+};
+
+void SalomePyQt::hideNotification( const QString& msg )
+{
+  ProcessVoidEvent( new THideNotifyEvent( msg ) );
+}
+
+void SalomePyQt::hideNotification( const int id )
+{
+  ProcessVoidEvent( new THideNotifyEvent( id ) );
+}
+
 /*!
   \fn const QString SalomePyQt::getActiveComponent();
   \brief Get the currently active module name (for the current study).
index 71875899811deb8ec0dbdc721f0357be75a3580f..2bac58d1a078d77594005f1f17bfde2bacf4f492 100644 (file)
@@ -190,12 +190,16 @@ public:
   static SALOME_Selection* getSelection();
   static void              setSelection( const QStringList& );
   static int               getStudyId();
-  static void              putInfo( const QString&, const int = 0 );
   static const QString     getActiveComponent();
   static PyObject*         getActivePythonModule();
   static bool              activateModule( const QString& );
   static void              updateObjBrowser( const int = 0, bool = true );
 
+  static void              putInfo( const QString&, const int = 0 );
+  static int               showNotification( const QString&, const QString&, const int = -1 );
+  static void              hideNotification( const QString& );
+  static void              hideNotification( const int );
+
   static bool              isModified();
   static void              setModified( bool );
 
index bf9a84a187b79d873df1e44937da057a9ab6c2a7..e7e726ccb8ef32e0e561d72cf9a2cb4a454b204d 100644 (file)
@@ -301,12 +301,16 @@ public:
   static SALOME_Selection* getSelection() /Factory,ReleaseGIL/ ;
   static void              setSelection( const QStringList& ) /ReleaseGIL/ ;
   static int               getStudyId() /ReleaseGIL/ ;
-  static void              putInfo( const QString&, const int = 0 ) /ReleaseGIL/ ;
   static const QString     getActiveComponent() /ReleaseGIL/ ;
   static SIP_PYOBJECT      getActivePythonModule() /ReleaseGIL/ ;
   static bool              activateModule( const QString& ) /ReleaseGIL/ ;
   static void              updateObjBrowser( const int = 0, bool =  true ) /ReleaseGIL/ ;
-  
+
+  static void              putInfo( const QString&, const int = 0 ) /ReleaseGIL/ ;
+  static int               showNotification( const QString&, const QString&, const int = -1 ) /ReleaseGIL/ ;
+  static void              hideNotification( const QString& ) /ReleaseGIL/ ;
+  static void              hideNotification( const int ) /ReleaseGIL/ ;
+
   static bool              isModified() /ReleaseGIL/ ;
   static void              setModified( bool ) /ReleaseGIL/ ;
 
index 208115b83d0397b4d388bd9a2bb50414cdcdbf87..1aacab91366299bf7ebb859421686e33ff18f674 100755 (executable)
@@ -53,6 +53,7 @@ extern "C" STD_EXPORT SUIT_Application* createApplication()
 STD_Application::STD_Application()
 : SUIT_Application(),
   myActiveViewMgr( 0 ),
+  myNotify( 0 ),
   myExitConfirm( true ),
   myEditEnabled( true )
 {
@@ -721,6 +722,56 @@ void STD_Application::updateCommandsStatus()
     action( NewWindowId )->setEnabled( aHasStudy );
 }
 
+/*!
+  \brief Show notification with specified text and title.
+  
+  Notification will be automatically hidden after specified \a timeout
+  (given in milliseconds). If \a timeout is zero, the notification
+  is not automatically hidden; it can be only closed by the user manually.
+  
+  \param text - Notification text
+  \param title - Notification title
+  \param timeout - Timeout in milliseconds
+  \return Notification's unique identifier
+*/
+int STD_Application::showNotification(const QString& message, const QString& title, int timeout)
+{
+  QtxNotify* ntfMgr = notifyMgr();
+  if (ntfMgr)
+  {
+    int delay = timeout;
+    if (delay < 0)
+    {
+      SUIT_ResourceMgr* aResMgr = resourceMgr();
+      if (aResMgr)
+       delay = aResMgr->integerValue("notification", "timeout", 0) * 1000;
+    }
+    ntfMgr->showNotification(message, title, qMax(delay, 0));
+  }
+}
+
+/*!
+  \brief Close notifications with specified text.
+  \param text - Notification text
+*/
+void STD_Application::hideNotification(const QString& message)
+{
+  QtxNotify* ntfMgr = notifyMgr();
+  if (ntfMgr)
+    ntfMgr->hideNotification(message);
+}
+
+/*!
+  \brief Closes the notifications with specified identifier.
+  \param id - Notification identifier
+*/
+void STD_Application::hideNotification(int id)
+{
+  QtxNotify* ntfMgr = notifyMgr();
+  if (ntfMgr)
+    ntfMgr->hideNotification(id);
+}
+
 /*!\retval SUIT_ViewManager by viewer manager type name.*/
 SUIT_ViewManager* STD_Application::viewManager( const QString& vmType ) const
 {
@@ -1037,3 +1088,27 @@ bool STD_Application::abortAllOperations()
 {
   return true;
 }
+
+/*!
+  \brief Gets the notification manager. Creates it if not exists.
+  \return \c notification manager instance
+*/
+QtxNotify* STD_Application::notifyMgr()
+{
+  if ( !myNotify )
+  {
+    myNotify = new QtxNotify(desktop());
+    myNotify->setWindow(desktop());
+
+    SUIT_ResourceMgr* aResMgr = resourceMgr();
+    if (aResMgr)
+    {
+      int anim = aResMgr->integerValue("notification", "animation", 0);
+      myNotify->setAnimationTime(anim);
+
+      double size = aResMgr->integerValue("notification", "size", 250);
+      myNotify->setNotificationSize(size);
+    }
+  }
+  return myNotify;
+}
index c709c95cdba23b748a499eb0a262c1fa2f349633..666024bd47289c13658a5df295d16d8fabd4ada6 100755 (executable)
 
 #include <SUIT_Application.h>
 
+#include <QtxNotify.h>
+
 #include <QList>
+#include <QPointer>
 
 class QMenu;
 class QCloseEvent;
@@ -104,6 +107,10 @@ public:
 
   virtual void          updateDesktopTitle();
 
+  int                   showNotification(const QString& message, const QString& title, int timeout = -1);
+  void                  hideNotification(const QString& message);
+  void                  hideNotification(int id);
+
 signals:
   /*!emit that view manager added*/
   void                  viewManagerAdded( SUIT_ViewManager* );
@@ -173,11 +180,15 @@ protected:
 
   virtual bool          abortAllOperations();
 
+ private:
+  QtxNotify*            notifyMgr();
+  
 private:
   ViewManagerList       myViewMgrs;
   SUIT_ViewManager*     myActiveViewMgr;
 
 private:
+  QPointer<QtxNotify>   myNotify;
   bool                  myExitConfirm;
   bool                  myEditEnabled;
 };