Exemple #1
0
    def refresh(self):
        """Refresh the display off notifications in the display zone

        Compact the remaining notifications in the display zone, if there is free slots, pop the notification queue and
        display the popup.

        """
        if len(self._displayed_popups
               ) >= self._max_popups:  # display zone is full
            return

        WIDGET_HEIGHT = get_default_config("WIDGET_HEIGHT", "int")
        WIDGET_WIDTH = get_default_config("WIDGET_WIDTH", "int")
        PADDING = get_default_config("WIDGET_PADDING", "int")
        i = 0  # position of the popup in the display zone
        """Compact the remaining popups"""
        for popup in self._displayed_popups:
            popup.setGeometry(
                QRect(self.ax, self.ay + i * (WIDGET_HEIGHT + PADDING),
                      WIDGET_WIDTH, WIDGET_HEIGHT))
            i += 1
        """Add new popups"""
        self._lock.acquire()
        if len(self._popup_queue) == 0:  # empty queue
            self._lock.release()
        else:  # notification waiting in queue
            new_notification = self._popup_queue.popleft()
            self._lock.release()
            self.display_popup(
                QRect(self.ax, self.ay + i * (WIDGET_HEIGHT + PADDING),
                      WIDGET_WIDTH, WIDGET_HEIGHT), new_notification)
def test_get_font_miss_two_arg(init_paths):
    """Tests the :class:`~_clockalarm.Notification.get_font` method without any
    font given.
    """
    notification = Notification("Test")
    font = notification.get_font()
    assert isinstance(font, QFont)
    assert font.family() == importExportUtils.get_default_config(
        "NOTIFICATION_FONT_FAMILY")
    assert font.pointSize() == importExportUtils.get_default_config(
        "NOTIFICATION_FONT_SIZE", "int")
    def get_sound(self):
        """Build a mixer.Sound object from sound parameter

        If the sound path parameter is missing, replace it with de default configuration.

        Returns:
            The mixer.Sound file of the notification

        """
        _sound_path = None
        if self.sound:  # existing sound path in Notification parameters
            _sound_path = pathlib.Path(
                join(base_path, "_clockalarm", "resources", "sounds",
                     self.sound)).as_posix()
        if _sound_path is None or not isfile(
                _sound_path):  # incorrect or missing sound path
            _sound_path = pathlib.Path(
                join(base_path, "_clockalarm", "resources", "sounds",
                     get_default_config("NOTIFICATION_SOUND"))).as_posix(
                     )  # replace with default sound path

        logging.log(1, "notification sound path: " + _sound_path)

        mixer.init()
        return mixer.Sound(
            _sound_path)  # returns the sound in a mixer.Sound object
Exemple #4
0
def test_mute_buton_click(init_paths, qtbot):
    """Test :class:~_clockalarm.UI.MainWindow.mute_button_click method."""
    global mw

    with qtbot.waitExposed(mw):
        mw.show()

    mute_before_click = importExportUtils.get_default_config('MUTE', 'bool')

    qtbot.mouseMove(mw, mw.mute_pushbutton.pos() + QPoint(10, 10))
    qtbot.mouseClick(mw.mute_pushbutton, QtCore.Qt.LeftButton)

    mute_after_click = importExportUtils.get_default_config('MUTE', 'bool')
    # Need to click again otherwise the some other tests may fail
    qtbot.mouseClick(mw.mute_pushbutton, QtCore.Qt.LeftButton)
    assert mute_before_click != mute_after_click
def test_get_font_miss_one_arg(init_paths):
    """Tests the :class:`~_clockalarm.Notification.get_font` method with one parameter missing
    """
    notification = Notification("Test", font_size=10)
    font = notification.get_font()
    assert isinstance(font, QFont)
    assert font.family() == importExportUtils.get_default_config(
        "NOTIFICATION_FONT_FAMILY")
    assert font.pointSize() == 10

    notification = Notification("Test", font_family="helvetica")
    font = notification.get_font()
    assert isinstance(font, QFont)
    assert font.family() == "helvetica"
    assert font.pointSize() == importExportUtils.get_default_config(
        "NOTIFICATION_FONT_SIZE", "int")
def test_app_constructor(before):
    """Tests the :class:`~_clockalarm.main.App` constructor.

    """
    argv = ["file", test_config_path, test_alertsDB_path]
    app = main.App(argv[1], argv[2], argv)

    assert app.CLOCK_FREQUENCY == importExportUtils.get_default_config("CLOCK_FREQUENCY", "int")
    assert app.MUTE == importExportUtils.get_default_config("MUTE", "bool")
    assert isinstance(app.main_window, MainWindow.MainWindow)
    assert isinstance(app.notification_center, NotificationCenter.NotificationCenter)
    assert isinstance(app.clock_thread, Clock)
    assert app.alert_collection is None  # alert_collection is not initializes in constructor

    app.init_alert_collection()
    assert isinstance(app.alert_collection, AlertCollection.AlertCollection)

    app.clock_thread.stop()
    app.alert_collection.db.close()
def test_get_color_miss_arg(init_paths):
    """Tests the :class:`~_clockalarm.Notification.get_color` method without any
    color given.
    """
    notification = Notification("Test")
    color = notification.get_color()

    assert isinstance(color, QColor)
    assert color.name() == importExportUtils.get_default_config(
        "NOTIFICATION_COLOR_HEX")
    def get_font(self):
        """Build a QFont from font_family and font_size
        
        If font_family or font_size parameter is missing, replace it with de default configuration.
        
        Returns:
            The QFont of the notification
            
        """
        if self.font_family and self.font_size:  # both parameters available
            return QFont(self.font_family, self.font_size)
        elif self.font_family:  # missing font_size
            return QFont(self.font_family,
                         get_default_config("NOTIFICATION_FONT_SIZE", "int"))
        elif self.font_size:  # missing font_family
            return QFont(get_default_config("NOTIFICATION_FONT_FAMILY"),
                         self.font_size)

        return QFont(get_default_config("NOTIFICATION_FONT_FAMILY"),
                     get_default_config("NOTIFICATION_FONT_SIZE",
                                        "int"))  # missing both parameters
 def init_ui(self, geom):
     """Helper method that sets the style of the NotificationWidget.
     
     Attributes:
         geom: The position and size of the widget on the screen
     """
     self.setGeometry(geom)
     self.setAttribute(Qt.WA_TranslucentBackground)
     self.setAttribute(Qt.WA_ShowWithoutActivating)
     """Background Image"""
     im_name = get_default_config("WIDGET_FILE_NAME")
     im_path = join(dirname(dirname(abspath(__file__))), 'resources',
                    'images', im_name)
     lbl_im = QLabel(self)
     lbl_im.setPixmap(QPixmap(im_path))
     """Notification message"""
     color = self.notification.get_color()
     alpha = get_default_config("WIDGET_TRANSPARENCY", "int")
     rgba = "{r}, {g}, {b}, {a}".format(r=color.red(),
                                        g=color.green(),
                                        b=color.blue(),
                                        a=alpha)
     lbl = QLabel(self.notification.message, self)
     lbl.setAlignment(Qt.AlignVCenter)
     lbl.setWordWrap(True)
     padding_top = get_default_config("WIDGET_TEXT_PADDING_TOP", "int")
     padding_left = get_default_config("WIDGET_TEXT_PADDING_LEFT", "int")
     text_width = get_default_config("WIDGET_TEXT_WIDTH", "int")
     text_height = get_default_config("WIDGET_TEXT_HEIGHT", "int")
     lbl.setGeometry(
         QRect(padding_left, padding_top, text_width, text_height))
     lbl.setFont(self.notification.get_font())
     lbl.setStyleSheet("QLabel { color : rgba(" + rgba + ")}")
    def get_color(self):
        """Build a QColor from color_hex parameter

        If color_hex parameter is missing, replace it with de default configuration.

        Returns:
            The QColor of the notification
            
        """
        if self.color_hex:
            return QColor(self.color_hex)
        return QColor(get_default_config(
            "NOTIFICATION_COLOR_HEX"))  # missing color_hex parameter
    def init_ui(self):
        """Initialisation of the main window GUI
        
        """
        icon_path = join(dirname(abspath(__file__)), 'resources', 'images',
                         get_default_config("ICON_FILE_NAME"))
        icon = QIcon(icon_path)
        self.setWindowIcon(icon)  # application icon for OSx and linux

        self.main_window = MainWindow(self)
        self.main_window.show()
        self.setQuitOnLastWindowClosed(
            False
        )  # app don't quit when last window is closed (reduced in tray)
Exemple #12
0
    def __init__(self, screen_geometry, parent=None):
        """Default NotificationCenter constructor

        Initialize the waiting queue and the list of displayed popups.
        Compute the maximum number of popup one can display on the screen.

        Attributes:
            screen_geometry (QRect): dimensions of the screen displaying the app
            parent (optional): parent class for NotificationCenter (usually main.App object)

        Exceptions:
            ValueError: In case of incorrect screen_geometry parameter

        """
        super(NotificationCenter, self).__init__()

        if not isinstance(screen_geometry, QRect) or screen_geometry is None:
            raise ValueError("screen_geometry must be a QRect object")

        self.parent = parent
        self._screen_geometry = screen_geometry
        self._max_popups = math.floor(
            (screen_geometry.height() * 0.9) /
            (get_default_config("WIDGET_HEIGHT", "int") +
             get_default_config("WIDGET_PADDING", "int"))
        )  # number of widget one can display with the given screen geometry

        self._popup_queue = deque([])  # list as a queue
        self._displayed_popups = []
        self._lock = threading.RLock()  # lock to protect the queue

        self.ax = self._screen_geometry.width() - get_default_config(
            "WIDGET_WIDTH",
            "int") - 20  # x coordinate of the notification zone in pixels
        self.ay = round(
            self._screen_geometry.height() *
            0.04)  # y coordinate of the notification zone in pixels
    def init_ui(self):
        """Init helper method to set up the main window."""
        self.setMinimumSize(QSize(300, 100))  # Set sizes
        self.setWindowTitle("ClockAlarm Manager")  # Set a title
        self.resize(get_default_config("MAIN_WINDOW_WIDTH", "int"),
                    get_default_config("MAIN_WINDOW_HEIGHT", "int"))

        import_action = QAction("Import Alerts File", self)
        import_action.triggered.connect(self.import_json_db)
        export_action = QAction("Export Alerts File", self)
        export_action.triggered.connect(self.export_json_db)
        quit_action = QAction("Exit", self)
        quit_action.triggered.connect(qApp.quit)

        new_alert_action = QAction("New Simple Alert", self)
        new_alert_action.triggered.connect(self.add_simple_alert)
        delete_alert_action = QAction("Delete Alert", self)
        delete_alert_action.triggered.connect(self.delete_alerts)
        edit_alert_action = QAction("Edit Alert", self)
        edit_alert_action.triggered.connect(self.edit_simple_alert)

        menu_bar = self.menuBar()
        file_menu = menu_bar.addMenu('&File')
        edit_menu = menu_bar.addMenu('&Edit')
        file_menu.addAction(import_action)
        file_menu.addAction(export_action)
        file_menu.addSeparator()
        file_menu.addAction(quit_action)

        edit_menu.addAction(new_alert_action)
        edit_menu.addAction(delete_alert_action)
        edit_menu.addAction(edit_alert_action)

        central_widget = QWidget(self)  # Create a central widget
        self.setCentralWidget(central_widget)  # Set the central widget

        grid_layout = QGridLayout(central_widget)  # Create a QGridLayout
        central_widget.setLayout(
            grid_layout)  # Set the layout into the central widget
        self.alert_list_widget = AlertListWidget()
        self.mute_pushbutton = QPushButton()
        if get_default_config("MUTE", "bool"):
            self.mute_pushbutton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaVolumeMuted))
        else:
            self.mute_pushbutton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaVolume))
        self.mute_pushbutton.clicked.connect(self.mute_button_click)

        grid_layout.addWidget(self.alert_list_widget, 0, 0)
        grid_layout.addWidget(self.mute_pushbutton, 1, 0, Qt.AlignRight)

        # Init QSystemTrayIcon
        icon_path = join(dirname(dirname(abspath(__file__))), 'resources',
                         'images', get_default_config("ICON_FILE_NAME"))
        icon = QIcon(icon_path)
        self.tray_icon = QSystemTrayIcon(self)
        self.tray_icon.setIcon(icon)
        self.tray_icon.activated.connect(self.tray_icon_click)

        tray_menu = QMenu()
        tray_menu.addAction(quit_action)
        self.tray_icon.setContextMenu(tray_menu)
        self.tray_icon.show()