diff --git a/README.md b/README.md new file mode 100644 index 0000000..7c52f9a --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +TuxClocker - A GUI overclocking utility for GNU/Linux +======================================== +TuxClocker is a Qt5 overclocking tool. Currently supported cards are nvidia 600-series cards and newer. Support for AMD GPUs is planned. + +# Current features +- GPU monitoring (list and graph) +- Overclocking +- Overvolting +- Change power limit +- Fan mode selection +- Custom fan curve +- Profiles + +# Planned features +- Multi-GPU support +- AMD support +- Rewrite nvidia controlling using libxnvctrl + +# Requirements + +- nvidia-smi +- nvidia-settings +- Qt libraries +- Coolbits set to the value you want (31 for all functionality) + +# Installation + +### Compilation +``` +git clone https://github.com/Lurkki14/tuxclocker +cd tuxclocker +qmake rojekti.pro +make +make install (installs into /opt/tuxclocker/bin) +``` + + diff --git a/editprofile.cpp b/editprofile.cpp index 18a314d..9042d3d 100644 --- a/editprofile.cpp +++ b/editprofile.cpp @@ -54,7 +54,7 @@ editProfile::editProfile(QWidget *parent) : ui->curvePlot->xAxis->setBasePen(tickPen); ui->curvePlot->yAxis->setBasePen(tickPen); - ui->curvePlot->xAxis->setLabel("Temperature"); + ui->curvePlot->xAxis->setLabel("Temperature (°C)"); ui->curvePlot->yAxis->setLabel("Fan speed (%)"); ui->curvePlot->xAxis->setRange(x_lower, (x_upper+5)); @@ -66,6 +66,7 @@ editProfile::editProfile(QWidget *parent) : connect(ui->curvePlot, SIGNAL(mouseMove(QMouseEvent*)), SLOT(detectMove(QMouseEvent*))); connect(ui->curvePlot, SIGNAL(mouseRelease(QMouseEvent*)), SLOT(detectRelease(QMouseEvent*))); connect(ui->curvePlot, SIGNAL(mouseMove(QMouseEvent*)), SLOT(getClosestCoords(QMouseEvent*))); + connect(ui->curvePlot, SIGNAL(mouseMove(QMouseEvent*)), SLOT(drawPointHoveredText(QMouseEvent*))); // Load the existing points to the graph MainWindow mw; @@ -78,6 +79,7 @@ editProfile::editProfile(QWidget *parent) : QCPItemText *text = new QCPItemText(ui->curvePlot); coordText = text; + coordText->setColor(textColor); } editProfile::~editProfile() @@ -90,7 +92,7 @@ void editProfile::addPoint(double x, double y) y = round(y); x = round(x); if (qv_x.length() != 0) { - checkForDuplicatePoint(x, y); + checkForDuplicatePoint(x, y); } if ((x_lower<=x) && (x<=x_upper) && (y_lower<=y) && (y<=y_upper) && !duplicatePoint) { qv_x.append(x); @@ -138,26 +140,43 @@ void editProfile::clickedPoint(QCPAbstractPlottable *plottable, int dataIndex, Q bool editProfile::checkForNearbyPoints(QMouseEvent *event) { if (qv_x.length() != 0) { - QPoint point = event->pos(); - double pointerxcoord = ui->curvePlot->xAxis->pixelToCoord(point.x()); - double pointerycoord = ui->curvePlot->yAxis->pixelToCoord(point.y()); - for (int i=0; ipos(); + double pointerxcoord = ui->curvePlot->xAxis->pixelToCoord(point.x()); + double pointerycoord = ui->curvePlot->yAxis->pixelToCoord(point.y()); + for (int i=0; iposition->setCoords(x_upper*0.1, xcoord + 4); + } else if (xcoord > x_upper*0.9) { + coordText->position->setCoords(x_upper*0.9, xcoord + 4); + } else { + coordText->position->setCoords(xcoord, ycoord + 4); + } + coordText->setText(QString::number(xcoord) + ", " + QString::number(ycoord)); + rePlot(); + } + if (!isNearbyPoint && !draggingPoint) { + coordText->setText(""); + rePlot(); + } +} int editProfile::getDataIndex(QCPAbstractPlottable *plottable, int dataIndex) { dataIndex = pointIndex; - qDebug() << pointIndex; return pointIndex; } @@ -212,9 +231,13 @@ bool editProfile::detectPress(QMouseEvent *event) bool editProfile::initializeDragging(QMouseEvent *event) { // Decides whether to start dragging the point + if (!pressTimer->isActive() && !mouseDragging) { + pressTimer->start(20); + pressTimer->setSingleShot(true); + } mouseDragging = true; checkForNearbyPoints(event); - if (isNearbyPoint || draggingPoint) { + if ((isNearbyPoint || draggingPoint) && pressTimer->remainingTime() <= 0) { dragPoint(index_x, index_y, event); draggingPoint = true; } @@ -255,16 +278,16 @@ void editProfile::dragPoint(int index_x, int index_y, QMouseEvent* event) qv_y[index_y] = y_lower; } // Display the coordinates - QPalette palette; - palette.setCurrentColorGroup(QPalette::Active); - QColor textColor = palette.color(QPalette::Text); - - coordText->position->setType(QCPItemPosition::ptPlotCoords); - coordText->position->setCoords(qv_x[index_x], qv_y[index_y] + 4); + if (ui->curvePlot->xAxis->pixelToCoord(point.x()) < x_upper*0.1) { + coordText->position->setCoords(x_upper*0.1, qv_y[index_y] + 4); + } else if (ui->curvePlot->xAxis->pixelToCoord(point.x()) > x_upper*0.9) { + coordText->position->setCoords(x_upper*0.9, qv_y[index_y] + 4); + } else { + coordText->position->setCoords(qv_x[index_x], qv_y[index_y] + 4); + } QString xString = QString::number(qv_x[index_x]); QString yString = QString::number(qv_y[index_y]); coordText->setText(xString + ", " + yString); - coordText->setColor(textColor); ui->curvePlot->graph(0)->setData(qv_x, qv_y); drawFillerLines(); @@ -298,12 +321,6 @@ void editProfile::detectRelease(QMouseEvent *event) rePlot(); } -void editProfile::on_pushButton_clicked() -{ - qDebug() << draggingPoint; - coordText->setText(""); -} - void editProfile::on_saveButton_clicked() { QString xString; @@ -316,24 +333,27 @@ void editProfile::on_saveButton_clicked() } MainWindow mw; - QVariant xarray = xString; - QVariant yarray = yString; - qDebug() << xarray.toString() << yarray.toString(); - QSettings settings("nvfancurve"); - QString xsetting = mw.currentProfile; - QString ysetting = mw.currentProfile; - ysetting.append("/ypoints"); - xsetting.append("/xpoints"); - settings.setValue(xsetting, xarray); - settings.setValue(ysetting, yarray); + QSettings settings("tuxclocker"); + settings.beginGroup("General"); + QString currentProfile = settings.value("currentProfile").toString(); + QString latestUUID = settings.value("latestUUID").toString(); + settings.endGroup(); + settings.beginGroup(currentProfile); + settings.beginGroup(latestUUID); + settings.setValue("ypoints", yString); + settings.setValue("xpoints", xString); + close(); } void editProfile::on_clearButton_clicked() { - MainWindow mw; qv_x.clear(); qv_y.clear(); - qDebug() << mw.currentProfile; ui->curvePlot->graph(0)->setData(qv_x, qv_y); drawFillerLines(); } + +void editProfile::on_cancelButton_pressed() +{ + close(); +} diff --git a/editprofile.h b/editprofile.h index 19b840c..3e845c8 100644 --- a/editprofile.h +++ b/editprofile.h @@ -29,7 +29,6 @@ private slots: void clickedGraph(QMouseEvent *event); void rePlot(); void addPoint(double x, double y); - void on_pushButton_clicked(); void clickedPoint(QCPAbstractPlottable *plottable, int dataIndex, QMouseEvent *event); void on_saveButton_clicked(); bool initializeDragging(QMouseEvent *event); @@ -44,6 +43,9 @@ private slots: void dragPoint(int index_x, int index_y, QMouseEvent *event); void drawFillerLines(); void on_clearButton_clicked(); + void drawPointHoveredText(QMouseEvent *event); + + void on_cancelButton_pressed(); private: Ui::editProfile *ui; @@ -76,6 +78,8 @@ private: int index_y = 0; bool indicesSet = false; bool draggingPoint = false; + QTimer *pressTimer = new QTimer(this); + int timerTime = 1000; }; #endif // EDITPROFILE_H diff --git a/editprofile.ui b/editprofile.ui index c2d4fd6..ee083aa 100644 --- a/editprofile.ui +++ b/editprofile.ui @@ -6,12 +6,18 @@ 0 0 - 663 - 565 + 642 + 557 + + + 599 + 523 + + - Dialog + Edit fan curve @@ -21,14 +27,14 @@ - + Clear curve points - + @@ -41,10 +47,10 @@ - - + + - testinappi + Cancel diff --git a/icon2.ico b/icon2.ico deleted file mode 100644 index e33ddd6..0000000 Binary files a/icon2.ico and /dev/null differ diff --git a/mainwindow.cpp b/mainwindow.cpp index 381d664..cada3d2 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -11,6 +11,7 @@ MainWindow::MainWindow(QWidget *parent) : ui(new Ui::MainWindow) { ui->setupUi(this); + checkForRoot(); checkForProfiles(); queryGPUSettings(); loadProfileSettings(); @@ -71,11 +72,6 @@ void MainWindow::on_actionEdit_current_profile_triggered(bool) editprof->show(); } -void MainWindow::on_pushButton_clicked() -{ - qDebug() << xCurvePoints; -} - void MainWindow::checkForRoot() { QProcess process; @@ -507,7 +503,7 @@ void MainWindow::clearExtremeValues() void MainWindow::checkForProfiles() { // If there are no profiles, create one, then list all the entries whose isProfile is true in the profile selection combo box - QSettings settings("nvfancurve"); + QSettings settings("tuxclocker"); QStringList groups = settings.childGroups(); QString isProfile = "/isProfile"; @@ -540,7 +536,12 @@ void MainWindow::checkForProfiles() void MainWindow::on_profileComboBox_activated(const QString &arg1) { // Change currentProfile to combobox selection - currentProfile = arg1; + if (currentProfile != arg1) { + currentProfile = arg1; + QSettings settings("tuxclocker"); + settings.setValue("General/currentProfile", currentProfile); + loadProfileSettings(); + } } void MainWindow::getGPUDriver() @@ -660,6 +661,8 @@ void MainWindow::applyFanMode() void MainWindow::queryGPUSettings() { QProcess process; + process.setReadChannelMode(QProcess::ForwardedErrorChannel); + process.setReadChannel(QProcess::StandardOutput); process.start(nvVoltQ); process.waitForFinished(-1); voltInt = process.readLine().toInt()/1000; @@ -675,6 +678,7 @@ void MainWindow::queryGPUSettings() process.waitForFinished(-1); for (int i=0; i maxVoltOfsInt) { + qDebug() << process.readLine(); maxVoltOfsInt = process.readLine().toInt()/1000; } } @@ -835,7 +839,7 @@ void MainWindow::applyGPUSettings() void MainWindow::loadProfileSettings() { - QSettings settings("nvfancurve"); + QSettings settings("tuxclocker"); currentProfile = settings.value("General/currentProfile").toString(); latestUUID = settings.value("General/latestUUID").toString(); settings.beginGroup(currentProfile); @@ -870,15 +874,27 @@ void MainWindow::loadProfileSettings() } if (settings.contains("voltageOffset")) { latestVoltOfs = settings.value("voltageOffset").toInt(); + + ui->voltageSlider->setValue(latestVoltOfs); + ui->voltageSpinBox->setValue(latestVoltOfs); } if (settings.contains("powerLimit")) { latestPowerLim = settings.value("powerLimit").toInt(); + + ui->powerLimSlider->setValue(latestPowerLim); + ui->powerLimSlider->setValue(latestPowerLim); } if (settings.contains("clockFrequencyOffset")) { latestClkOfs = settings.value("clockFrequencyOffset").toInt(); + + ui->frequencySlider->setValue(latestClkOfs); + ui->frequencySpinBox->setValue(latestClkOfs); } if (settings.contains("memoryClockOffset")) { latestMemClkOfs=settings.value("memoryClockOffset").toInt(); + + ui->memClkSlider->setValue(latestMemClkOfs); + ui->memClkSlider->setValue(latestMemClkOfs); } if (settings.contains("fanControlMode")) { fanControlMode = settings.value("fanControlMode").toInt(); @@ -892,7 +908,7 @@ void MainWindow::loadProfileSettings() void MainWindow::on_newProfile_closed() { // If currentProfile doesn't exist anymore the first profile will be the first entry - QSettings settings("nvfancurve"); + QSettings settings("tuxclocker"); QStringList groups = settings.childGroups(); if (!groups.contains(currentProfile)) { for (int i=0; isetAttribute(Qt::WA_DeleteOnClose); + connect(np, SIGNAL(destroyed(QObject*)), SLOT(on_newProfile_closed())); + np->setModal(false); + np->exec(); +} + +/*void MainWindow::on_profileComboBox_currentTextChanged(const QString &arg1) +{ + +}*/ diff --git a/mainwindow.h b/mainwindow.h index b2b63a4..7826936 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -6,8 +6,7 @@ #include "monitor.h" #include #include -#include -//#include "/opt/cuda/include/nvml.h" +#include //#include namespace Ui { @@ -98,7 +97,6 @@ public slots: private slots: void on_actionEdit_current_profile_triggered(bool checked); - void on_pushButton_clicked(); void on_profileComboBox_activated(const QString &arg1); void queryGPUSettings(); @@ -153,6 +151,8 @@ private slots: void plotHovered(QMouseEvent *event); void clearPlots(); void clearExtremeValues(); + void on_actionManage_profiles_triggered(); + private: Ui::MainWindow *ui; bool noProfiles = true; @@ -177,6 +177,7 @@ private: QTreeWidgetItem *memusage = new QTreeWidgetItem; QTreeWidgetItem *curmaxclk = new QTreeWidgetItem; QTreeWidgetItem *curmaxmemclk = new QTreeWidgetItem; + QTreeWidgetItem *curpowerlim = new QTreeWidgetItem; // Widgets for the graph monitor QWidget *plotWidget = new QWidget(this); diff --git a/mainwindow.ui b/mainwindow.ui index 68d4f9b..3bdd7cd 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -11,11 +11,11 @@ - MainWindow + TuxClocker - - + + QTabWidget::Rounded @@ -28,13 +28,6 @@ Performance - - - - testinappi - - - @@ -76,13 +69,6 @@ - - - - Apply changes - - - @@ -119,6 +105,9 @@ 16777215 + + <html><head/><body><p>Edit fan curve</p></body></html> + @@ -180,19 +169,19 @@ - - - - ... - - - + + + + Apply changes + + + @@ -239,19 +228,11 @@ - Fi&le + Profi&les - - - - - P&rofiles - - - + - @@ -274,6 +255,11 @@ &Add new profile + + + &Manage profiles + + diff --git a/newprofile.cpp b/newprofile.cpp index 399676b..c4f6c51 100644 --- a/newprofile.cpp +++ b/newprofile.cpp @@ -28,21 +28,18 @@ void newProfile::on_profileNameEdit_textChanged(const QString &arg1) } void newProfile::saveChange() { - qDebug() << "edit finished"; + //qDebug() << "edit finished"; //QListWidgetItem *item = ui->profileList->item(latestIndex); newProfileList.clear(); for (int i=0; iprofileList->count(); i++) { newProfileList.append(ui->profileList->item(i)->text()); - qDebug() << newProfileList[i]; + //qDebug() << newProfileList[i]; ui->profileList->item(i)->setFlags(Qt::ItemIsEnabled); } } void newProfile::on_saveButton_clicked() { - QSettings settings("nvfancurve"); - //settings.beginGroup("rtgerdg"); - //settings.remove(""); - qDebug() << removedList; + QSettings settings("tuxclocker"); // Add the new ones for (int i=0; iprofileList->addItem(groups[i]); origProfileList.append(groups[i]); newProfileList.append(groups[i]); @@ -102,22 +100,10 @@ void newProfile::on_removeButton_pressed() { if (ui->profileList->count() > 1) { int index = ui->profileList->currentRow(); - qDebug() << index; - //QListWidgetItem *item = new QListWidgetItem(ui->profileList); QListWidgetItem *item = ui->profileList->item(index); removedList.append(item->text()); newProfileList.removeAt(index); - - //newProfileList.removeAt(index); - - //item = ui->profileList->item(index); ui->profileList->takeItem(index); - /*if (ui->profileList->currentRow() == ui->profileList->count()-1) { - ui->profileList->model()->removeRow(index); - } else { - ui->profileList->model()->removeRow(index +1); - }*/ - //ui->profileList->model()->removeRow(ui->profileList->count()-1); delete item; } } diff --git a/newprofile.ui b/newprofile.ui index 92947dc..d74a59d 100644 --- a/newprofile.ui +++ b/newprofile.ui @@ -11,7 +11,7 @@ - Dialog + Manage profiles diff --git a/resources.qrc b/resources.qrc index 4f74bda..480449a 100644 --- a/resources.qrc +++ b/resources.qrc @@ -1,8 +1,8 @@ cog.png - icon2.ico plusicon.png minusicon.png + gpuonfire.svg diff --git a/rojekti.pro b/rojekti.pro index 02e0c53..519e387 100644 --- a/rojekti.pro +++ b/rojekti.pro @@ -4,11 +4,11 @@ # #------------------------------------------------- -QT += core gui x11extras +QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets printsupport -TARGET = rojekti +TARGET = tuxclocker TEMPLATE = app # The following define makes your compiler emit warnings if you use @@ -23,7 +23,9 @@ DEFINES += QT_DEPRECATED_WARNINGS #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 CONFIG += c++11 - +#CONFIG (release, debug|release) { +# DEFINES += QT_NO_DEBUG_OUTPUT +# } SOURCES += \ main.cpp \ mainwindow.cpp \ @@ -48,9 +50,9 @@ FORMS += \ editprofile.ui \ newprofile.ui -INCLUDEPATH += "/usr/lib" +#INCLUDEPATH += "/usr/lib" -LIBS += -lXext -lXNVCtrl -lX11 +#LIBS += -lXext -lXNVCtrl -lX11 # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin