Commit fede0d74 authored by Roberto Leinardi's avatar Roberto Leinardi

Merge branch 'feature/oc-profiles' into 'master'

Add overclock profiles

Closes #23

See merge request !19
parents 27c06c43 981ed4ac
......@@ -32,6 +32,7 @@ if __name__ == '__main__':
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
gi.require_version('Notify', '0.7')
from gi.repository import Gio
......
Version 0.11.0
==============
Released: 2019-02-10
* Add overclock profiles
* Fixed GPU offset overclock not working for some cards
* Showing notification via libnotify if an update is available
* Added PCIe current generation info
Version 0.10.4
==============
Released: 2019-02-09
......
......@@ -79,8 +79,8 @@ ninja -v -C build install
- [x] Find better icons for app indicator
- [x] Try to lower resource consumption (mostly caused by `nvidia-settings` invocations)
- [x] Show historical data of most important values in a separate dialog (requires GTK 3.24/GNOME 3.30)
- [ ] Add overclock profiles
- [ ] Add option to restore last applied overclock profile on app startup
- [x] Add overclock profiles
- [x] Add option to restore last applied overclock profile on app startup
- [ ] Disable unsupported preferences
- [x] Distributing with Flatpack
- [x] Publishing on Flathub
......
......@@ -43,6 +43,7 @@ if __name__ == '__main__':
gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')
gi.require_version('Notify', '0.7')
from gi.repository import Gio
resource = Gio.Resource.load(os.path.join(PKGDATA_DIR, 'com.leinardi.gwe.gresource'))
......
......@@ -27,6 +27,16 @@
<url type="bugtracker">https://gitlab.com/leinardi/gwe/issues</url>
<update_contact>roberto@leinardi.com</update_contact>
<releases>
<release date="2019-02-10" version="0.11.0">
<description>
<ul>
<li>Add overclock profiles</li>
<li>Fixed GPU offset overclock not working for some cards</li>
<li>Showing notification via libnotify if an update is available</li>
<li>Added PCIe current generation info</li>
</ul>
</description>
</release>
<release date="2019-02-9" version="0.10.4">
<description>
<ul>
......
......@@ -5,6 +5,7 @@
<file preprocess="xml-stripblanks">ui/main.glade</file>
<file preprocess="xml-stripblanks">ui/edit_fan_profile.glade</file>
<file preprocess="xml-stripblanks">ui/edit_oc_profile.glade</file>
<file preprocess="xml-stripblanks">ui/historical_data.glade</file>
<file preprocess="xml-stripblanks">ui/preferences.glade</file>
......
......@@ -60,7 +60,7 @@ along with GWE. If not, see <http://www.gnu.org/licenses/>.
<property name="show_close_button">True</property>
<child>
<object class="GtkButton" id="delete_profile_button">
<property name="label">Delete profile</property>
<property name="label">Delete</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
......
This diff is collapsed.
This diff is collapsed.
......@@ -220,7 +220,7 @@ along with GWE. If not, see <http://www.gnu.org/licenses/>.
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes" comments="Translators: This switch reverses the scrolling direction for mices. The term used comes from OS X so use the same translation if possible.">Load last profile</property>
<property name="label" translatable="yes" comments="Translators: This switch reverses the scrolling direction for mices. The term used comes from OS X so use the same translation if possible.">Load last fan and overclock profile</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
</object>
......@@ -233,7 +233,7 @@ along with GWE. If not, see <http://www.gnu.org/licenses/>.
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Automatically apply last used fan profile when the app starts</property>
<property name="label" translatable="yes">Automatically apply last used fan and overclock profile when the app starts</property>
<property name="xalign">0</property>
<attributes>
<attribute name="scale" value="0.90000000000000002"/>
......
......@@ -16,7 +16,6 @@
# along with gwe. If not, see <http://www.gnu.org/licenses/>.
import logging
import sys
from enum import Enum
from gettext import gettext as _
from typing import Any, Optional, List
......@@ -27,7 +26,8 @@ from peewee import SqliteDatabase
from gwe.conf import APP_NAME, APP_ID, APP_VERSION, APP_ICON_NAME
from gwe.di import MainBuilder
from gwe.model import FanProfile, SpeedStep, Setting, CurrentFanProfile, load_db_default_data
from gwe.model import FanProfile, SpeedStep, Setting, CurrentFanProfile, load_fan_db_default_data, OverclockProfile, \
load_overclock_db_default_data, CurrentOverclockProfile
from gwe.presenter.main import MainPresenter
from gwe.repository import NvidiaRepository
from gwe.util.deployment import is_flatpak
......@@ -56,10 +56,19 @@ class Application(Gtk.Application):
**kwargs)
database.connect()
database.create_tables([FanProfile, SpeedStep, CurrentFanProfile, Setting])
database.create_tables([
SpeedStep,
FanProfile,
CurrentFanProfile,
OverclockProfile,
CurrentOverclockProfile,
Setting
])
if FanProfile.select().count() == 0:
load_db_default_data()
load_fan_db_default_data()
if OverclockProfile.select().count() == 0:
load_overclock_db_default_data()
self.add_main_option_entries(self._get_main_option_entries())
self._view = view
......
......@@ -25,6 +25,7 @@ APP_ICON_NAME_SYMBOLIC = APP_ID + "-symbolic"
APP_DB_NAME = APP_PACKAGE_NAME + ".db"
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"
APP_HISTORICAL_DATA_UI_NAME = "historical_data.glade"
APP_PREFERENCES_UI_NAME = "preferences.glade"
APP_DESKTOP_ENTRY_NAME = APP_PACKAGE_NAME + ".desktop"
......
......@@ -24,15 +24,17 @@ from rx.disposables import CompositeDisposable
from rx.subjects 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
from gwe.util.path import get_data_path, get_config_path
APP_PREFERENCES_UI_NAME, APP_HISTORICAL_DATA_UI_NAME, APP_EDIT_OC_PROFILE_UI_NAME
from gwe.util.path import get_config_path
LOG = logging.getLogger(__name__)
FanProfileChangedSubject = Key("FanProfileChangedSubject")
SpeedStepChangedSubject = Key("SpeedStepChangedSubject")
FanProfileChangedSubject = Key("FanProfileChangedSubject")
OverclockProfileChangedSubject = Key("OverclockProfileChangedSubject")
MainBuilder = Key(APP_MAIN_UI_NAME)
EditFanProfileBuilder = Key(APP_EDIT_FAN_PROFILE_UI_NAME)
EditOverclockProfileBuilder = Key(APP_EDIT_OC_PROFILE_UI_NAME)
HistoricalDataBuilder = Key(APP_HISTORICAL_DATA_UI_NAME)
PreferencesBuilder = Key(APP_PREFERENCES_UI_NAME)
......@@ -45,7 +47,7 @@ class ProviderModule(Module):
LOG.debug("provide Gtk.Builder")
builder = Gtk.Builder()
builder.set_translation_domain(APP_PACKAGE_NAME)
builder.add_from_resource("/com/leinardi/gwe/ui/{0}".format(APP_MAIN_UI_NAME))
builder.add_from_resource("/com/leinardi/gwe/ui/{}".format(APP_MAIN_UI_NAME))
return builder
@singleton
......@@ -54,7 +56,16 @@ class ProviderModule(Module):
LOG.debug("provide Gtk.Builder")
builder = Gtk.Builder()
builder.set_translation_domain(APP_PACKAGE_NAME)
builder.add_from_resource("/com/leinardi/gwe/ui/{0}".format(APP_EDIT_FAN_PROFILE_UI_NAME))
builder.add_from_resource("/com/leinardi/gwe/ui/{}".format(APP_EDIT_FAN_PROFILE_UI_NAME))
return builder
@singleton
@provider
def provide_edit_overclock_profile_builder(self) -> EditOverclockProfileBuilder:
LOG.debug("provide Gtk.Builder")
builder = Gtk.Builder()
builder.set_translation_domain(APP_PACKAGE_NAME)
builder.add_from_resource("/com/leinardi/gwe/ui/{}".format(APP_EDIT_OC_PROFILE_UI_NAME))
return builder
@singleton
......@@ -63,7 +74,7 @@ class ProviderModule(Module):
LOG.debug("provide Gtk.Builder")
builder = Gtk.Builder()
builder.set_translation_domain(APP_PACKAGE_NAME)
builder.add_from_resource("/com/leinardi/gwe/ui/{0}".format(APP_HISTORICAL_DATA_UI_NAME))
builder.add_from_resource("/com/leinardi/gwe/ui/{}".format(APP_HISTORICAL_DATA_UI_NAME))
return builder
@singleton
......@@ -72,7 +83,7 @@ class ProviderModule(Module):
LOG.debug("provide Gtk.Builder")
builder = Gtk.Builder()
builder.set_translation_domain(APP_PACKAGE_NAME)
builder.add_from_resource("/com/leinardi/gwe/ui/{0}".format(APP_PREFERENCES_UI_NAME))
builder.add_from_resource("/com/leinardi/gwe/ui/{}".format(APP_PREFERENCES_UI_NAME))
return builder
@singleton
......@@ -87,6 +98,11 @@ class ProviderModule(Module):
LOG.debug("provide CompositeDisposable")
return SqliteDatabase(get_config_path(APP_DB_NAME))
@singleton
@provider
def provide_speed_step_changed_subject(self) -> SpeedStepChangedSubject:
return Subject()
@singleton
@provider
def provide_fan_profile_changed_subject(self) -> FanProfileChangedSubject:
......@@ -94,7 +110,7 @@ class ProviderModule(Module):
@singleton
@provider
def provide_speed_step_changed_subject(self) -> SpeedStepChangedSubject:
def provide_overclock_profile_changed_subject(self) -> OverclockProfileChangedSubject:
return Subject()
......
......@@ -25,11 +25,12 @@ from playhouse.sqlite_ext import AutoIncrementField
from peewee import CharField, DateTimeField, SqliteDatabase, SQL, IntegerField, Check, \
ForeignKeyField, BooleanField, BlobField
from gwe.di import INJECTOR, FanProfileChangedSubject, SpeedStepChangedSubject
from gwe.di import INJECTOR, FanProfileChangedSubject, SpeedStepChangedSubject, OverclockProfileChangedSubject
LOG = logging.getLogger(__name__)
FAN_PROFILE_CHANGED_SUBJECT = INJECTOR.get(FanProfileChangedSubject)
SPEED_STEP_CHANGED_SUBJECT = INJECTOR.get(SpeedStepChangedSubject)
FAN_PROFILE_CHANGED_SUBJECT = INJECTOR.get(FanProfileChangedSubject)
OVERCLOCK_PROFILE_CHANGED_SUBJECT = INJECTOR.get(OverclockProfileChangedSubject)
class Info:
......@@ -37,7 +38,8 @@ class Info:
name: Optional[str] = None,
vbios: Optional[str] = None,
driver: Optional[str] = None,
pcie_generation: Optional[int] = None,
pcie_current_generation: Optional[int] = None,
pcie_max_generation: Optional[int] = None,
pcie_current_link: Optional[int] = None,
pcie_max_link: Optional[int] = None,
cuda_cores: Optional[int] = None,
......@@ -53,7 +55,8 @@ class Info:
self.name: Optional[str] = name
self.vbios: Optional[str] = vbios
self.driver: Optional[str] = driver
self.pcie_generation: Optional[int] = pcie_generation
self.pcie_current_generation: Optional[int] = pcie_current_generation
self.pcie_max_generation: Optional[int] = pcie_max_generation
self.pcie_current_link: Optional[int] = pcie_current_link
self.pcie_max_link: Optional[int] = pcie_max_link
self.cuda_cores: Optional[int] = cuda_cores
......@@ -245,6 +248,49 @@ class CurrentFanProfile(Model):
database = INJECTOR.get(SqliteDatabase)
class OverclockProfileType(Enum):
DEFAULT = 'default'
OFFSET = 'offset'
class OverclockProfile(Model):
id = AutoIncrementField()
type = CharField(
constraints=[Check("type='%s' OR type='%s'" % (
OverclockProfileType.DEFAULT.value, OverclockProfileType.OFFSET.value))],
default=OverclockProfileType.OFFSET.value)
name = CharField()
gpu = IntegerField(default=0)
memory = IntegerField(default=0)
read_only = BooleanField(default=False)
timestamp = DateTimeField(constraints=[SQL('DEFAULT CURRENT_TIMESTAMP')])
class Meta:
legacy_table_names = False
database = INJECTOR.get(SqliteDatabase)
@post_save(sender=OverclockProfile)
def on_overclock_profile_added(_: Any, profile: OverclockProfile, created: bool) -> None:
LOG.debug("Profile added")
OVERCLOCK_PROFILE_CHANGED_SUBJECT.on_next(DbChange(profile, DbChange.INSERT if created else DbChange.UPDATE))
@post_delete(sender=OverclockProfile)
def on_overclock_profile_deleted(_: Any, profile: OverclockProfile) -> None:
LOG.debug("Profile deleted")
OVERCLOCK_PROFILE_CHANGED_SUBJECT.on_next(DbChange(profile, DbChange.DELETE))
class CurrentOverclockProfile(Model):
profile = ForeignKeyField(OverclockProfile, unique=True)
timestamp = DateTimeField(constraints=[SQL('DEFAULT CURRENT_TIMESTAMP')])
class Meta:
legacy_table_names = False
database = INJECTOR.get(SqliteDatabase)
class Setting(Model):
key = CharField(primary_key=True)
value = BlobField()
......@@ -254,7 +300,7 @@ class Setting(Model):
database = INJECTOR.get(SqliteDatabase)
def load_db_default_data() -> None:
def load_fan_db_default_data() -> None:
FanProfile.create(name="Auto (VBIOS controlled)", type=FanProfileType.AUTO.value, read_only=True)
fan_silent = FanProfile.create(name="Custom")
......@@ -265,3 +311,7 @@ def load_db_default_data() -> None:
SpeedStep.create(profile=fan_silent.id, temperature=65, duty=70)
SpeedStep.create(profile=fan_silent.id, temperature=70, duty=90)
SpeedStep.create(profile=fan_silent.id, temperature=75, duty=100)
def load_overclock_db_default_data() -> None:
OverclockProfile.create(type=OverclockProfileType.DEFAULT.value, name="Default", gpu=0, memory=0, read_only=True)
......@@ -107,10 +107,6 @@ class EditFanProfilePresenter:
self.refresh_controls(step, True)
def on_add_profile_clicked(self, *_: Any) -> None:
self._profile.delete_instance(recursive=True)
self.view.hide()
def on_delete_profile_clicked(self, *_: Any) -> None:
self._profile.delete_instance(recursive=True)
self.view.hide()
......
# This file is part of gwe.
#
# Copyright (c) 2018 Roberto Leinardi
#
# gwe is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gwe 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gwe. If not, see <http://www.gnu.org/licenses/>.
import logging
import multiprocessing
from typing import Any
from gi.repository import Gtk
from injector import singleton, inject
from rx.concurrency import GtkScheduler, ThreadPoolScheduler
from rx.concurrency.schedulerbase import SchedulerBase
from rx.disposables import CompositeDisposable
from gwe.interactor import SetOverclockInteractor
from gwe.model import OverclockProfile, Overclock
from gwe.util.view import hide_on_delete
LOG = logging.getLogger(__name__)
class EditOverclockProfileViewInterface:
def show(self, profile: OverclockProfile, overclock: Overclock) -> None:
raise NotImplementedError()
def hide(self) -> None:
raise NotImplementedError()
def get_profile_name(self) -> str:
raise NotImplementedError()
def get_gpu_offset(self) -> int:
raise NotImplementedError()
def get_memory_offset(self) -> int:
raise NotImplementedError()
@singleton
class EditOverclockProfilePresenter:
@inject
def __init__(self,
set_overclock_interactor: SetOverclockInteractor,
composite_disposable: CompositeDisposable
) -> None:
LOG.debug("init EditOverclockProfilePresenter")
self._set_overclock_interactor = set_overclock_interactor
self._composite_disposable: CompositeDisposable = composite_disposable
self.view: EditOverclockProfileViewInterface = EditOverclockProfileViewInterface()
self._profile = OverclockProfile()
self._overclock = Overclock()
self._scheduler: SchedulerBase = ThreadPoolScheduler(multiprocessing.cpu_count())
def show_add(self, overclock: Overclock) -> None:
profile = OverclockProfile()
profile.name = 'New profile'
profile.save()
self.show_edit(profile, overclock)
def show_edit(self, profile: OverclockProfile, overclock: Overclock) -> None:
self._profile = profile
self._overclock = overclock
self.view.show(profile, overclock)
def on_dialog_delete_event(self, widget: Gtk.Widget, *_: Any) -> Any:
self._save_profile_name()
return hide_on_delete(widget)
def on_delete_profile_button_clicked(self, *_: Any) -> None:
self._profile.delete_instance(recursive=True)
self.view.hide()
def on_apply_offsets_button_clicked(self, *_: Any) -> None:
gpu_index = 0
self._composite_disposable.add(self._set_overclock_interactor.execute(
gpu_index, self._overclock.perf_level_max, self.view.get_gpu_offset(), self.view.get_memory_offset())
.subscribe_on(self._scheduler)
.observe_on(GtkScheduler())
.subscribe(on_next=self._handle_set_overclock_result,
on_error=self._handle_set_overclock_result)
)
def on_save_offsets_button_clicked(self, *_: Any) -> None:
self._profile.gpu = self.view.get_gpu_offset()
self._profile.memory = self.view.get_memory_offset()
self._profile.name = self.view.get_profile_name()
self._profile.save()
self.view.hide()
def _save_profile_name(self) -> None:
if self._profile is not None:
name = self.view.get_profile_name()
if name != self._profile.name:
self._profile.name = name
self._profile.save()
@staticmethod
def _handle_set_overclock_result(result: Any) -> bool:
if not isinstance(result, bool) or not result:
LOG.exception("Set overclock error: %s", str(result))
return False
else:
return True
This diff is collapsed.
......@@ -102,7 +102,8 @@ class NvidiaRepository:
name=self._nvml_get_val(py3nvml.nvmlDeviceGetName, handle),
vbios=self._nvml_get_val(py3nvml.nvmlDeviceGetVbiosVersion, handle),
driver=self._nvml_get_val(py3nvml.nvmlSystemGetDriverVersion),
pcie_generation=self._nvml_get_val(py3nvml.nvmlDeviceGetMaxPcieLinkGeneration, handle),
pcie_current_generation=self._nvml_get_val(py3nvml.nvmlDeviceGetCurrPcieLinkGeneration, handle),
pcie_max_generation=self._nvml_get_val(py3nvml.nvmlDeviceGetMaxPcieLinkGeneration, handle),
pcie_current_link=self._nvml_get_val(py3nvml.nvmlDeviceGetCurrPcieLinkWidth, handle),
pcie_max_link=self._nvml_get_val(py3nvml.nvmlDeviceGetMaxPcieLinkWidth, handle),
cuda_cores=xlib_display.nvcontrol_get_cuda_cores(gpu),
......@@ -135,22 +136,23 @@ class NvidiaRepository:
else:
clocks = Clocks()
mem_transfer_rate_offset_range = xlib_display.nvcontrol_get_mem_transfer_rate_offset_range(gpu)
perf_level = xlib_display.nvcontrol_get_current_performance_level(gpu)
perf_level_max = perf_mode.get('perf') if perf_mode else None
mem_transfer_rate_offset_range = \
xlib_display.nvcontrol_get_mem_transfer_rate_offset_range(gpu, perf_level_max)
if mem_transfer_rate_offset_range is not None:
mem_clock_offset_range = (mem_transfer_rate_offset_range[0] // 2,
mem_transfer_rate_offset_range[1] // 2)
mem_transfer_rate_offset = xlib_display.nvcontrol_get_mem_transfer_rate_offset(gpu, perf_level)
mem_transfer_rate_offset = xlib_display.nvcontrol_get_mem_transfer_rate_offset(gpu, perf_level_max)
mem_clock_offset = None
if mem_transfer_rate_offset is not None:
mem_clock_offset = mem_transfer_rate_offset // 2
overclock = Overclock(
available=mem_transfer_rate_offset is not None,
gpu_range=xlib_display.nvcontrol_get_gpu_nvclock_offset_range(gpu),
gpu_offset=xlib_display.nvcontrol_get_gpu_nvclock_offset(gpu, perf_level),
gpu_range=xlib_display.nvcontrol_get_gpu_nvclock_offset_range(gpu, perf_level_max),
gpu_offset=xlib_display.nvcontrol_get_gpu_nvclock_offset(gpu, perf_level_max),
memory_range=mem_clock_offset_range,
memory_offset=mem_clock_offset,
perf_level_max=perf_mode.get('perf') if perf_mode else None
perf_level_max=perf_level_max
)
else:
overclock = Overclock(perf_level_max=perf_mode.get('perf') if perf_mode else None)
......
......@@ -16,13 +16,13 @@
# along with gwe. If not, see <http://www.gnu.org/licenses/>.
from typing import Optional, Any, Dict
from gi.repository import Notify
from gi.repository import GLib, Gtk, Gdk
from matplotlib.axes import Axes
from matplotlib.backends.backend_gtk3agg import FigureCanvasGTK3Agg as FigureCanvas
from matplotlib.figure import Figure
from gwe.conf import MIN_TEMP, MAX_TEMP, FAN_MAX_DUTY, GRAPH_COLOR_HEX
from gwe.conf import MIN_TEMP, MAX_TEMP, FAN_MAX_DUTY, GRAPH_COLOR_HEX, APP_NAME
from gwe.model import FanProfile
......@@ -110,3 +110,9 @@ def is_dazzle_version_supported() -> bool:
if Gtk.MAJOR_VERSION >= 3 and Gtk.MINOR_VERSION >= 24: # Mypy says that this check returns Any, not sure why...
return True
return False
def show_notification(summary: str, body: str, icon: str) -> None:
if Notify.init(APP_NAME):
hello = Notify.Notification.new(summary=summary, body=body, icon=icon)
hello.show()
# This file is part of gwe.
#
# Copyright (c) 2018 Roberto Leinardi
#
# gwe is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# gwe 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with gwe. If not, see <http://www.gnu.org/licenses/>.
import logging
from gi.repository import Gtk
from injector import singleton, inject
from gwe.di import EditOverclockProfileBuilder
from gwe.model import OverclockProfile, Overclock
from gwe.presenter.edit_overclock_profile import EditOverclockProfileViewInterface, EditOverclockProfilePresenter
LOG = logging.getLogger(__name__)
@singleton
class EditOverclockProfileView(EditOverclockProfileViewInterface):
@inject
def __init__(self,
presenter: EditOverclockProfilePresenter,
builder: EditOverclockProfileBuilder,
) -> None:
LOG.debug('init EditOverclockProfileView')
self._presenter: EditOverclockProfilePresenter = presenter
self._presenter.view = self
self._builder: Gtk.Builder = builder
self._builder.connect_signals(self._presenter)
self._init_widgets()
def _init_widgets(self) -> None:
self._dialog: Gtk.Dialog = self._builder.get_object('dialog')
self._delete_profile_button: Gtk.Button = self._builder.get_object('delete_profile_button')
self._profile_name_entry: Gtk.Entry = self._builder.get_object('profile_name_entry')
self._apply_offsets_button: Gtk.Button = self._builder.get_object('apply_offsets_button')
self._save_offsets_button: Gtk.Button = self._builder.get_object('save_offsets_button')
self._gpu_offset_scale: Gtk.Scale = self._builder.get_object('gpu_offset_scale')
self._memory_offset_scale: Gtk.Scale = self._builder.get_object('memory_offset_scale')
self._gpu_offset_adjustment: Gtk.Adjustment = self._builder.get_object(
'gpu_offset_adjustment')
self._memory_offset_adjustment: Gtk.Adjustment = self._builder.get_object(
'memory_offset_adjustment')
def set_transient_for(self, window: Gtk.Window) -> None:
self._dialog.set_transient_for(window)
def show(self, profile: OverclockProfile, overclock: Overclock) -> None:
self._update_ui(profile, overclock)
self._dialog.show_all()
def hide(self) -> None:
self._dialog.hide()
def get_profile_name(self) -> str:
return str(self._profile_name_entry.get_text())
def get_gpu_offset(self) -> int:
return int(self._gpu_offset_adjustment.get_value())
def get_memory_offset(self) -> int:
return int(self._memory_offset_adjustment.get_value())
def _update_ui(self, profile: OverclockProfile, overclock: Overclock) -> None:
self._profile_name_entry.set_text(profile.name)
self._profile_name_entry.set_text(profile.name)
self._gpu_offset_adjustment.set_lower(overclock.gpu_range[0])
self._gpu_offset_adjustment.set_upper(overclock.gpu_range[1])
self._memory_offset_adjustment.set_lower(overclock.memory_range[0])
self._memory_offset_adjustment.set_upper(overclock.memory_range[1])
self._gpu_offset_adjustment.set_value(profile.gpu)
self._memory_offset_adjustment.set_value(profile.memory)
self._gpu_offset_scale.clear_marks()
self._gpu_offset_scale.add_mark(0, Gtk.PositionType.BOTTOM, str(0))
self._memory_offset_scale.clear_marks()
self._memory_offset_scale.add_mark(0, Gtk.PositionType.BOTTOM, str(0))
......@@ -32,6 +32,7 @@ from matplotlib.backends.backend_gtk3agg import FigureCanvasGTK3Agg as FigureCan
# AppIndicator3 may not be installed
from gwe.interactor import SettingsInteractor
from gwe.view.edit_overclock_profile import EditOverclockProfileView
from gwe.view.historical_data import HistoricalDataView
from gwe.view.preferences import PreferencesView
......@@ -57,6 +58,7 @@ class MainView(MainViewInterface):
def __init__(self,
presenter: MainPresenter,
edit_fan_profile_view: EditFanProfileView,
edit_overclock_profile_view: EditOverclockProfileView,
historical_data_view: HistoricalDataView,
preferences_view: PreferencesView,
builder: MainBuilder,
......@@ -65,6 +67,7 @@ class MainView(MainViewInterface):
LOG.debug('init MainView')
self._presenter: MainPresenter = presenter
self._edit_fan_profile_view = edit_fan_profile_view
self._edit_overclock_profile_view = edit_overclock_profile_view
self._historical_data_view = historical_data_view
self._preferences_view = preferences_view
self._presenter.main_view = self
......@@ -72,12 +75,12 @@ class MainView(MainViewInterface):
self._settings_interactor = settings_interactor
self._first_refresh = True
self._init_widgets()
self._latest_status: Optional[Status] = None
def _init_widgets(self) -> None:
self._app_indicator: Optional[AppIndicator3.Indicator] = None
self._window = self._builder.get_object("application_window")
self._edit_fan_profile_view.set_transient_for(self._window)
self._edit_overclock_profile_view.set_transient_for(self._window)
self._historical_data_view.set_transient_for(self._window)
self._preferences_view.set_transient_for(self._window)
self._main_menu: Gtk.Menu = self._builder.get_object("main_menu")
......@@ -117,6 +120,8 @@ class MainView(MainViewInterface):
self._clocks_memory_max_entry: Gtk.Entry = self._builder.get_object('clocks_memory_max_entry')
self._clocks_video_current_entry: Gtk.Entry = self._builder.get_object('clocks_video_current_entry')
self._clocks_video_max_entry: Gtk.Entry = self._builder.get_object('clocks_video_max_entry')
self._overclock_gpu_offset_entry: Gtk.Entry = self._builder.get_object('overclock_gpu_offset_entry')
self._overclock_mem_offset_entry: Gtk.Entry = self._builder.get_object('overclock_mem_offset_entry')
self._info_memory_usage_levelbar: Gtk.LevelBar = self._builder.get_object('info_memory_usage_levelbar')
self._info_gpu_usage_levelbar: Gtk.LevelBar = self._builder.get_object('info_gpu_usage_levelbar')
self._info_encoder_usage_levelbar: Gtk.LevelBar = self._builder.get_object('info_encoder_usage_levelbar')
......@@ -144,20 +149,17 @@ class MainView(MainViewInterface):
self._fan_profile_frame: Gtk.Frame = self._builder.get_object('fan_profile_frame')
self._overclock_frame: Gtk.Frame = self._builder.get_object('overclock_frame')
self._power_limit_scale: Gtk.Scale = self._builder.get_object('power_limit_scale')
self._overclock_gpu_offset_scale: Gtk.Scale = self._builder.get_object('overclock_gpu_offset_scale')
self._overclock_memory_offset_scale: Gtk.Scale = self._builder.get_object('overclock_memory_offset_scale')
self._power_limit_adjustment: Gtk.Adjustment = self._builder.get_object('power_limit_adjustment')
self._overclock_gpu_offset_adjustment: Gtk.Adjustment = self._builder.get_object(
'overclock_gpu_offset_adjustment')
self._overclock_memory_offset_adjustment: Gtk.Adjustment = self._builder.get_object(
'overclock_memory_offset_adjustment')
self._fan_apply_button: Gtk.Button = self._builder.get_object('fan_apply_button')
self._overclock_apply_button: Gtk.Button = self._builder.get_object('overclock_apply_button')
self._power_limit_apply_button: Gtk.Button = self._builder.get_object('power_limit_apply_button')
self._fan_liststore: Gtk.ListStore = self._builder.get_object('fan_profile_liststore')
self._overclock_liststore: Gtk.ListStore = self._builder.get_object('overclock_profile_liststore')
self._fan_combobox: Gtk.ComboBox = self._builder.get_object('fan_profile_combobox')
self._overclock_combobox: Gtk.ComboBox = self._builder.get_object('overclock_profile_combobox')
fan_scrolled_window: Gtk.ScrolledWindow = self._builder.get_object('fan_scrolled_window')
self._fan_edit_button: Gtk.Button = self._builder.get_object('fan_edit_button')
self._overclock_edit_button: Gtk.Button = self._builder.get_object('overclock_edit_button')
self._init_plot_charts(fan_scrolled_window)
if not is_dazzle_version_supported():
self._builder.get_object("historical_data_button").set_sensitive(False)
......@@ -203,14 +205,6 @@ class MainView(MainViewInterface):
def get_power_limit(self) -> Tuple[int, int]:
return 0, self._power_limit_adjustment.get_value()
def get_overclock_offsets(self) -> Tuple[int, int, int, int]:
return (
0,
self._latest_status.gpu_status_list[0].overclock.perf_level_max,
int(self._overclock_gpu_offset_adjustment.get_value()),
int(self._overclock_memory_offset_adjustment.get_value())
)
def show_about_dialog(self) -> None:
self._about_dialog.show()
......@@ -221,7 +215,6 @@ class MainView(MainViewInterface):
def refresh_status(self, status: Optional[Status]) -> None:
LOG.debug('view status')
if status:
self._latest_status = status
gpu_status = status.gpu_status_list[0]
if self._first_refresh:
self._first_refresh = False
......@@ -259,22 +252,11 @@ class MainView(MainViewInterface):
self._power_limit_scale.set_sensitive(False)