Skip to content
This repository was archived by the owner on Oct 12, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions data/ui/edit_fan_profile.glade
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1
<!-- Generated with glade 3.22.2

Copyright (C)

Expand Down Expand Up @@ -185,6 +185,22 @@ along with GWE. If not, see <http://www.gnu.org/licenses/>.
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="vbios_silent_mode">
<property name="label" translatable="yes">VBIOS control on low temps</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Some GPUs (e.g. RTX 3060 Ti) do not allow fan speed to be set below a certain level (e.g. 30%) in manual speed control mode. This option allows you to disable the fans by switching to VBIOS controller mode when the temperature is below the minimum temperature on the chart. May produce undefined behavior. This option is useless on GPUs that allow any fan speed to be set.</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="vbios_silent_mode_toggled" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
Expand Down Expand Up @@ -345,7 +361,7 @@ along with GWE. If not, see <http://www.gnu.org/licenses/>.
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
<property name="position">3</property>
</packing>
</child>
</object>
Expand Down
2 changes: 1 addition & 1 deletion flatpak
2 changes: 1 addition & 1 deletion gwe/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

from peewee import SqliteDatabase
from gi.repository import GLib
from rx.disposable import CompositeDisposable
from reactivex.disposable import CompositeDisposable

from gwe.conf import APP_PACKAGE_NAME
from gwe.model.current_fan_profile import CurrentFanProfile
Expand Down
9 changes: 8 additions & 1 deletion gwe/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# along with gwe. If not, see <http://www.gnu.org/licenses/>.

import logging
from time import sleep
from enum import Enum
from gettext import gettext as _
from typing import Any, Optional, List
Expand Down Expand Up @@ -113,14 +114,17 @@ def do_command_line(self, command_line: Gio.ApplicationCommandLine) -> int:

if _Options.AUTOSTART_OFF.value in options:
_LOG.debug(f"Option {_Options.AUTOSTART_OFF.value} selected")
set_autostart_entry(True)
set_autostart_entry(False)
start_app = False

if _Options.CTRL_DISPLAY.value in options:
param = options[_Options.CTRL_DISPLAY.value]
_LOG.debug(f"Option {_Options.CTRL_DISPLAY.value} selected: {param}")
self._nvidia_repository.set_ctrl_display(param)

if _Options.DELAY.value in options:
sleep(3)

if start_app:
self.activate()
return exit_value
Expand All @@ -135,6 +139,8 @@ def _get_main_option_entries() -> List[GLib.OptionEntry]:
description="Show the App version"),
build_glib_option(_Options.HIDE_WINDOW.value,
description="Start with the main window hidden"),
build_glib_option(_Options.DELAY.value,
description="Set a small delay on start"),
build_glib_option(_Options.CTRL_DISPLAY.value,
arg=GLib.OptionArg.STRING,
description="Specify the NV-CONTROL display (if you use Bumblebee, set this to \":8\" "
Expand All @@ -155,3 +161,4 @@ class _Options(Enum):
CTRL_DISPLAY = 'ctrl-display'
AUTOSTART_ON = 'autostart-on'
AUTOSTART_OFF = 'autostart-off'
DELAY = 'delay'
1 change: 1 addition & 0 deletions gwe/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
APP_ICON_NAME = APP_ID
APP_ICON_NAME_SYMBOLIC = APP_ID + "-symbolic"
APP_DB_NAME = APP_PACKAGE_NAME + ".db"
APP_DB_VERSION = 1
APP_MAIN_UI_NAME = "main.glade"
APP_EDIT_FAN_PROFILE_UI_NAME = "edit_fan_profile.glade"
APP_EDIT_OC_PROFILE_UI_NAME = "edit_oc_profile.glade"
Expand Down
41 changes: 33 additions & 8 deletions gwe/di.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,20 @@
# You should have received a copy of the GNU General Public License
# along with gwe. If not, see <http://www.gnu.org/licenses/>.

import os
import logging
import shutil
from typing import NewType

from gi.repository import Gtk
from injector import Module, provider, singleton, Injector
from peewee import SqliteDatabase
from rx.disposable import CompositeDisposable
from rx.subject import Subject
from peewee import SqliteDatabase, BooleanField
from playhouse.migrate import SqliteMigrator, migrate
from reactivex.disposable import CompositeDisposable
from reactivex.subject import Subject

from gwe.conf import APP_PACKAGE_NAME, APP_MAIN_UI_NAME, APP_DB_NAME, APP_EDIT_FAN_PROFILE_UI_NAME, \
APP_PREFERENCES_UI_NAME, APP_HISTORICAL_DATA_UI_NAME, APP_EDIT_OC_PROFILE_UI_NAME
APP_PREFERENCES_UI_NAME, APP_HISTORICAL_DATA_UI_NAME, APP_EDIT_OC_PROFILE_UI_NAME, APP_DB_VERSION
from gwe.util.path import get_config_path

_LOG = logging.getLogger(__name__)
Expand Down Expand Up @@ -96,13 +99,35 @@ def provide_thread_pool_scheduler(self) -> CompositeDisposable:
_LOG.debug("provide CompositeDisposable")
return CompositeDisposable()

@staticmethod
def _create_database(path_to_db: str) -> SqliteDatabase:
database = SqliteDatabase(path_to_db)

if os.path.exists(path_to_db):
if database.pragma('user_version') == 0:
_LOG.debug("upgrading database to version 1")
shutil.copyfile(path_to_db, path_to_db + '.bak')

database.pragma('user_version', 1, permanent=True)

migrator = SqliteMigrator(database)
vbios_silent_mode = BooleanField(default=False)
migrate(
migrator.add_column('fan_profile', 'vbios_silent_mode', vbios_silent_mode),
migrator.add_column('current_fan_profile', 'vbios_silent_mode', vbios_silent_mode)
)

database.commit()
else:
database.pragma('user_version', APP_DB_VERSION, permanent=True)

return database

@singleton
@provider
def provide_database(self) -> SqliteDatabase:
_LOG.debug("provide SqliteDatabase")
database = SqliteDatabase(get_config_path(APP_DB_NAME))
database.connect()
return database
return self._create_database(get_config_path(APP_DB_NAME))

@singleton
@provider
Expand All @@ -121,7 +146,7 @@ def provide_overclock_profile_changed_subject(self) -> OverclockProfileChangedSu

@singleton
@provider
def provide_overclock_profile_changed_subject(self) -> SettingChangedSubject:
def provide_setting_changed_subject(self) -> SettingChangedSubject:
return SettingChangedSubject(Subject())


Expand Down
6 changes: 3 additions & 3 deletions gwe/interactor/check_new_version_interactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
from typing import Optional

import requests
import rx
import reactivex
from injector import singleton, inject
from rx import Observable
from reactivex import Observable

from gwe.conf import APP_ID, APP_VERSION

Expand All @@ -39,7 +39,7 @@ def __init__(self) -> None:

def execute(self) -> Observable:
_LOG.debug("CheckNewVersionInteractor.execute()")
return rx.defer(lambda _: rx.just(self._check_new_version()))
return reactivex.defer(lambda _: reactivex.just(self._check_new_version()))

def _check_new_version(self) -> Optional[LooseVersion]:
req = requests.get(self.URL_PATTERN.format(package=APP_ID))
Expand Down
6 changes: 3 additions & 3 deletions gwe/interactor/get_status_interactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
#
# You should have received a copy of the GNU General Public License
# along with gst. If not, see <http://www.gnu.org/licenses/>.
import rx
import reactivex
from injector import singleton, inject
from rx import Observable
from reactivex import Observable

from gwe.repository.nvidia_repository import NvidiaRepository

Expand All @@ -29,4 +29,4 @@ def __init__(self, nvidia_repository: NvidiaRepository, ) -> None:

def execute(self) -> Observable:
# _LOG.debug("GetStatusInteractor.execute()")
return rx.defer(lambda _: rx.just(self._nvidia_repository.get_status()))
return reactivex.defer(lambda _: reactivex.just(self._nvidia_repository.get_status()))
6 changes: 3 additions & 3 deletions gwe/interactor/has_nvidia_driver_interactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
# along with gst. If not, see <http://www.gnu.org/licenses/>.
from enum import Enum, auto

import rx
import reactivex
from injector import singleton, inject
from rx import Observable
from reactivex import Observable

from gwe.repository.nvidia_repository import NvidiaRepository

Expand All @@ -36,7 +36,7 @@ def __init__(self, nvidia_repository: NvidiaRepository, ) -> None:
self._nvidia_repository = nvidia_repository

def execute(self) -> Observable:
return rx.defer(lambda _: rx.just(self._has_nvidia_driver()))
return reactivex.defer(lambda _: reactivex.just(self._has_nvidia_driver()))

def _has_nvidia_driver(self) -> HasNvidiaDriverResult:
if not self._nvidia_repository.has_nv_control_extension():
Expand Down
8 changes: 4 additions & 4 deletions gwe/interactor/set_fan_speed_interactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
# along with gst. If not, see <http://www.gnu.org/licenses/>.
import logging

import rx
import reactivex
from injector import singleton, inject
from rx import Observable
from reactivex import Observable

from gwe.repository.nvidia_repository import NvidiaRepository

Expand All @@ -33,5 +33,5 @@ def __init__(self, nvidia_repository: NvidiaRepository, ) -> None:

def execute(self, gpu_index: int, speed: int = 100, manual_control: bool = True) -> Observable:
_LOG.debug("SetSpeedProfileInteractor.execute()")
return rx.defer(
lambda _: rx.just(self._nvidia_repository.set_fan_speed(gpu_index, speed, manual_control)))
return reactivex.defer(
lambda _: reactivex.just(self._nvidia_repository.set_fan_speed(gpu_index, speed, manual_control)))
8 changes: 4 additions & 4 deletions gwe/interactor/set_overclock_interactor.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
# along with gst. If not, see <http://www.gnu.org/licenses/>.
import logging

import rx
import reactivex
from injector import singleton, inject
from rx import Observable
from reactivex import Observable

from gwe.repository.nvidia_repository import NvidiaRepository

Expand All @@ -33,5 +33,5 @@ def __init__(self, nvidia_repository: NvidiaRepository, ) -> None:

def execute(self, gpu_index: int, perf: int, gpu_offset: int, memory_offset: int) -> Observable:
_LOG.debug("SetOverclockInteractor.execute()")
return rx.defer(
lambda _: rx.just(self._nvidia_repository.set_overclock(gpu_index, perf, gpu_offset, memory_offset)))
return reactivex.defer(
lambda _: reactivex.just(self._nvidia_repository.set_overclock(gpu_index, perf, gpu_offset, memory_offset)))
6 changes: 3 additions & 3 deletions gwe/interactor/set_power_limit_iInteractor.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
# along with gst. If not, see <http://www.gnu.org/licenses/>.
import logging

import rx
import reactivex
from injector import singleton, inject
from rx import Observable
from reactivex import Observable

from gwe.repository.nvidia_repository import NvidiaRepository

Expand All @@ -33,4 +33,4 @@ def __init__(self, nvidia_repository: NvidiaRepository, ) -> None:

def execute(self, gpu_index: int, limit: int) -> Observable:
_LOG.debug("SetPowerLimitInteractor.execute()")
return rx.defer(lambda _: rx.just(self._nvidia_repository.set_power_limit(gpu_index, limit)))
return reactivex.defer(lambda _: reactivex.just(self._nvidia_repository.set_power_limit(gpu_index, limit)))
7 changes: 6 additions & 1 deletion gwe/model/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,12 @@


def load_fan_db_default_data() -> None:
FanProfile.create(name="Auto (VBIOS controlled)", type=FanProfileType.AUTO.value, read_only=True)
FanProfile.create(
name="Auto (VBIOS controlled)",
type=FanProfileType.AUTO.value,
read_only=True,
vbios_silent_mode=False
)
fan_silent = FanProfile.create(name="Custom")

# Fan Silent
Expand Down
3 changes: 2 additions & 1 deletion gwe/model/current_fan_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#
# You should have received a copy of the GNU General Public License
# along with gst. If not, see <http://www.gnu.org/licenses/>.
from peewee import ForeignKeyField, DateTimeField, SQL, SqliteDatabase
from peewee import ForeignKeyField, DateTimeField, BooleanField, SQL, SqliteDatabase
from playhouse.signals import Model

from gwe.di import INJECTOR
Expand All @@ -24,6 +24,7 @@
class CurrentFanProfile(Model):
profile = ForeignKeyField(FanProfile, unique=True)
timestamp = DateTimeField(constraints=[SQL('DEFAULT CURRENT_TIMESTAMP')])
vbios_silent_mode = BooleanField(default=False)

class Meta:
legacy_table_names = False
Expand Down
1 change: 1 addition & 0 deletions gwe/model/fan_profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class FanProfile(Model):
name = CharField()
read_only = BooleanField(default=False)
timestamp = DateTimeField(constraints=[SQL('DEFAULT CURRENT_TIMESTAMP')])
vbios_silent_mode = BooleanField(default=False)

class Meta:
legacy_table_names = False
Expand Down
2 changes: 1 addition & 1 deletion gwe/model/fan_profile_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@

class FanProfileType(Enum):
AUTO = 'auto'
FAN_CURVE = 'fan_curve'
FAN_CURVE = 'fan_curve'
11 changes: 9 additions & 2 deletions gwe/presenter/edit_fan_profile_presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ def get_duty(self) -> int:
def has_a_step_selected(self) -> bool:
raise NotImplementedError()

def refresh_controls(self, step: Optional[SpeedStep] = None, unselect_list: bool = False) -> None:
def refresh_controls(self,
step: Optional[SpeedStep] = None,
unselect_list: bool = False,
profile: Optional[FanProfile] = None) -> None:
raise NotImplementedError()

def refresh_liststore(self, profile: FanProfile) -> None:
Expand Down Expand Up @@ -89,7 +92,11 @@ def on_dialog_delete_event(self, widget: Gtk.Widget, *_: Any) -> Any:

def refresh_controls(self, step: Optional[SpeedStep] = None, deselect_list: bool = False) -> None:
self._selected_step = step
self.view.refresh_controls(step, deselect_list)
self.view.refresh_controls(step, deselect_list, self._profile)

def vbios_silent_mode_toggled(self, widget: Gtk.ToggleButton) -> None:
self._profile.vbios_silent_mode = widget.get_active()
self._profile.save()

def on_step_selected(self, tree_selection: Gtk.TreeSelection) -> None:
_LOG.debug("selected")
Expand Down
8 changes: 4 additions & 4 deletions gwe/presenter/edit_overclock_profile_presenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@

from gi.repository import Gtk, GLib
from injector import singleton, inject
from rx import operators
from rx.disposable import CompositeDisposable
from rx.scheduler import ThreadPoolScheduler
from rx.scheduler.mainloop import GtkScheduler
from reactivex import operators
from reactivex.disposable import CompositeDisposable
from reactivex.scheduler import ThreadPoolScheduler
from reactivex.scheduler.mainloop import GtkScheduler

from gwe.interactor.set_overclock_interactor import SetOverclockInteractor
from gwe.model.overclock_profile import OverclockProfile
Expand Down
Loading