Commit 14372762 authored by Melroy van den Berg's avatar Melroy van den Berg
Browse files

Several bug fixed, introduced settings window/edit window. Code clean-up and more!

parent e65d3350
......@@ -50,7 +50,7 @@ link_directories(${GTKMM_LIBRARY_DIRS})
add_definitions(${GTKMM_CFLAGS_OTHER})
add_library(menu_lib src/menu.cc)
add_library(windows_lib src/main_window.cc src/preferences_window.cc src/settings_window.cc)
add_library(windows_lib src/main_window.cc src/preferences_window.cc src/edit_window.cc src/settings_window.cc)
add_library(bottle_manager_lib src/bottle_manager.cc)
add_library(bottle_item src/bottle_item.cc)
add_library(new_bottle_assis_lib src/new_bottle_assistant.cc)
......
......@@ -34,7 +34,6 @@ using std::string;
class MainWindow;
class SignalDispatcher;
/**
* \class BottleManager
* \brief Controller that controls it all
......@@ -42,6 +41,9 @@ class SignalDispatcher;
class BottleManager
{
public:
// Signals
sigc::signal<void> resetActiveBottle; /*!< Send signal: Clear the current active bottle */
BottleManager(MainWindow& mainWindow);
virtual ~BottleManager();
......@@ -57,6 +59,7 @@ public:
void DeleteBottle();
const Glib::ustring& GetErrorMessage();
void RunProgram(string filename, bool is_msi_file);
const Glib::ustring& GetActiveBottleName();
void SetActiveBottle(BottleItem* bottle);
private:
// Synchronizes access to data members
......@@ -68,7 +71,7 @@ private:
BottleItem* activeBottle;
//// error_message is used by both the GUI thread and NewBottle thread (used a 'temp' location)
Glib::ustring error_message;
Glib::ustring m_error_message;
string GetWineVersion();
std::map<string, unsigned long> GetBottlePaths();
......
/**
* Copyright (c) 2020 WineGUI
*
* \file edit_window.h
* \brief Edit GTK+ window class
* \author Melroy van den Berg <webmaster1989@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <gtkmm.h>
using std::string;
// Forward declaration
class BottleItem;
//class SignalDispatcher;
/**
* \class SettingsWindow
* \brief GTK+ Window class for the settings
*/
class EditWindow : public Gtk::Window
{
public:
EditWindow(Gtk::Window& parent);
virtual ~EditWindow();
void Show();
//void SetDispatcher(SignalDispatcher& signalDispatcher); Could be useful?
void SetActiveBottle(BottleItem* bottle);
void ResetActiveBottle();
protected:
// Child widgets
Gtk::Grid settings_grid;
Gtk::Label first_row_label;
Gtk::Label second_row_label;
Gtk::Toolbar first_toolbar;
Gtk::Toolbar second_toolbar;
// Buttons first row
Gtk::ToolButton edit_button; /*!< edit button */
Gtk::ToolButton delete_button; /*!< delete button */
// Buttons second row
Gtk::ToolButton wine_config_button; /*!< Winecfg button */
private:
BottleItem* activeBottle; /*!< Current active bottle */
// Private methods
};
......@@ -51,6 +51,7 @@ public:
static bool GetBottleStatus(const string prefix_path);
static string GetCLetterDrive(const string prefix_path);
static bool DirExists(const string& dir_path);
static bool CreateDir(const string& dir_path);
static bool FileExists(const string& filer_path);
static void InstallOrUpdateWinetricks();
static void SelfUpdateWinetricks();
......
......@@ -93,8 +93,8 @@ protected:
// Toolbar buttons
Gtk::ToolButton new_button; /*!< New toolbar button */
Gtk::ToolButton run_button; /*!< Run... toolbar button */
Gtk::ToolButton edit_button; /*!< Edit toolbar button */
Gtk::ToolButton settings_button; /*!< Settings toolbar button */
Gtk::ToolButton manage_button; /*!< Manage toolbar button */
Gtk::ToolButton reboot_button; /*!< Reboot toolbar button */
private:
......
......@@ -34,8 +34,8 @@ public:
sigc::signal<void> signal_refresh; /*!< on refresh button clicked signal */
sigc::signal<void> signal_new_machine; /*!< on new button clicked signal */
sigc::signal<void> signal_run; /*!< on new new button clicked signal */
sigc::signal<void> signal_edit_machine; /*!< on edit button clicked signal */
sigc::signal<void> signal_settings_machine; /*!< on settings button clicked signal */
sigc::signal<void> signal_manage_machine; /*!< on manage button clicked signal */
sigc::signal<void> signal_remove_machine; /*!< on remove button clicked signal */
sigc::signal<void> signal_show_about; /*!< on about button clicked signal */
......
/**
* Copyright (c) 2019 WineGUI
* Copyright (c) 2020 WineGUI
*
* \file settings_window.h
* \brief Settings GTK+ window class
......@@ -20,12 +20,12 @@
*/
#pragma once
#include "bottle_item.h"
#include <gtkmm.h>
using std::string;
// Forward declaration
class BottleItem;
//class SignalDispatcher;
/**
......@@ -37,10 +37,11 @@ class SettingsWindow : public Gtk::Window
public:
SettingsWindow(Gtk::Window& parent);
virtual ~SettingsWindow();
//void SetDispatcher(SignalDispatcher& signalDispatcher); Could be useful?
void Show();
//void SetDispatcher(SignalDispatcher& signalDispatcher); Could be useful?
void SetActiveBottle(BottleItem* bottle);
void ResetActiveBottle();
protected:
// Child widgets
Gtk::Grid settings_grid;
......@@ -58,7 +59,7 @@ protected:
Gtk::ToolButton wine_config_button; /*!< Winecfg button */
private:
BottleItem* currentBottle; /*!< Current bottle to manage settings */
BottleItem* activeBottle; /*!< Current active bottle */
// Private methods
......
......@@ -30,6 +30,7 @@ class BottleManager;
class Menu;
class PreferencesWindow;
class AboutDialog;
class EditWindow;
class SettingsWindow;
/**
......@@ -42,9 +43,15 @@ class SignalDispatcher : public Gtk::Window
public:
// Signals
sigc::signal<void> signal_show_settings_window; /*!< show settings window signal */
sigc::signal<void> signal_show_edit_window; /*!< show Edit window signal */
sigc::signal<void> signal_show_settings_window; /*!< show Settings window signal */
SignalDispatcher(BottleManager& manager, Menu& menu, PreferencesWindow& preferencesWindow, AboutDialog& about, SettingsWindow& settingsWindow);
SignalDispatcher(BottleManager& manager,
Menu& menu,
PreferencesWindow& preferencesWindow,
AboutDialog& about,
EditWindow& editWindow,
SettingsWindow& settingsWindow);
virtual ~SignalDispatcher();
void SetMainWindow(MainWindow* mainWindow);
void DispatchSignals();
......@@ -74,6 +81,7 @@ private:
Menu& menu;
PreferencesWindow& preferencesWindow;
AboutDialog& about;
EditWindow& editWindow;
SettingsWindow& settingsWindow;
// Dispatcher for handling signals from the thread towards a GUI thread
......
......@@ -32,7 +32,7 @@ BottleItem::BottleItem() {
* \brief Copy contructor, used by GTK+
*/
BottleItem::BottleItem(const BottleItem& bottleItem) : BottleItem() {
if( this != &bottleItem ) {
if ( this != &bottleItem ) {
_name = bottleItem.name();
_is_status_ok = bottleItem.status();
_win = bottleItem.windows();
......@@ -125,7 +125,7 @@ void BottleItem::CreateUI()
name_label.set_markup("<span size=\"medium\"><b>" + name + "</b></span>");
Glib::ustring status_text = "Ready";
if(status) {
if (status) {
status_icon.set(IMAGE_LOCATION "ready.png");
} else {
status_text = "Not Ready";
......
......@@ -35,7 +35,7 @@ BottleManager::BottleManager(MainWindow& mainWindow):
m_Mutex(),
mainWindow(mainWindow),
activeBottle(nullptr),
error_message()
m_error_message()
{
// TODO: Make it configurable via settings
std::vector<std::string> dirs{Glib::get_home_dir(), ".winegui", "prefixes"};
......@@ -90,7 +90,7 @@ void BottleManager::Prepare()
void BottleManager::UpdateBottles()
{
// Clear bottles
if(bottles.size() > 0)
if (bottles.size() > 0)
bottles.clear();
// Get the bottle directories
......@@ -115,7 +115,7 @@ void BottleManager::UpdateBottles()
return; // stop
}
if(bottles.size() > 0)
if (bottles.size() > 0)
{
// Update main Window
mainWindow.SetWineBottles(bottles);
......@@ -129,14 +129,19 @@ void BottleManager::UpdateBottles()
}
else
{
mainWindow.ShowErrorMessage("Could not create an overview of Windows Machines. Empty list.");
// Set active bottle to NULL
mainWindow.ShowErrorMessage("Could not create an overview of Windows Machines. Empty list.");
// Send reset signal to reset the active bottle to NULL
resetActiveBottle.emit();
// Reset locally
this->activeBottle = nullptr;
}
}
else
{
// Set active bottle to NULL
// Send reset signal to reset the active bottle to NULL
resetActiveBottle.emit();
// Reset locally
this->activeBottle = nullptr;
}
}
......@@ -172,7 +177,7 @@ void BottleManager::NewBottle(
{
{
std::lock_guard<std::mutex> lock(m_Mutex);
error_message = ("Something went wrong during creation of a new Windows machine!\n" +
m_error_message = ("Something went wrong during creation of a new Windows machine!\n" +
Glib::ustring(error.what()));
}
caller->SignalErrorMessage();
......@@ -180,10 +185,10 @@ void BottleManager::NewBottle(
}
// Continue with additional settings
if(bottle_created)
if (bottle_created)
{
// Only change Windows OS when NOT default
if(windows_version != WineDefaults::WINDOWS_OS)
if (windows_version != WineDefaults::WINDOWS_OS)
{
try {
Helper::SetWindowsVersion(wine_prefix, windows_version);
......@@ -192,7 +197,7 @@ void BottleManager::NewBottle(
{
{
std::lock_guard<std::mutex> lock(m_Mutex);
error_message = ("Something went wrong during setting another Windows version.\n" +
m_error_message = ("Something went wrong during setting another Windows version.\n" +
Glib::ustring(error.what()));
}
caller->SignalErrorMessage();
......@@ -201,7 +206,7 @@ void BottleManager::NewBottle(
}
// Only if virtual desktop is not empty, enable it
if(!virtual_desktop_resolution.empty())
if (!virtual_desktop_resolution.empty())
{
try {
Helper::SetVirtualDesktop(wine_prefix, virtual_desktop_resolution);
......@@ -210,7 +215,7 @@ void BottleManager::NewBottle(
{
{
std::lock_guard<std::mutex> lock(m_Mutex);
error_message = ("Something went wrong during enabling virtual desktop mode.\n" +
m_error_message = ("Something went wrong during enabling virtual desktop mode.\n" +
Glib::ustring(error.what()));
}
caller->SignalErrorMessage();
......@@ -219,7 +224,7 @@ void BottleManager::NewBottle(
}
// Only if Audio driver is not default, change it
if(audio != WineDefaults::AUDIO_DRIVER)
if (audio != WineDefaults::AUDIO_DRIVER)
{
try {
Helper::SetAudioDriver(wine_prefix, audio);
......@@ -228,7 +233,7 @@ void BottleManager::NewBottle(
{
{
std::lock_guard<std::mutex> lock(m_Mutex);
error_message = ("Something went wrong during setting another audio driver.\n" +
m_error_message = ("Something went wrong during setting another audio driver.\n" +
Glib::ustring(error.what()));
}
caller->SignalErrorMessage();
......@@ -255,7 +260,7 @@ void BottleManager::NewBottle(
*/
void BottleManager::DeleteBottle()
{
if(activeBottle != nullptr)
if (activeBottle != nullptr)
{
try
{
......@@ -289,7 +294,7 @@ void BottleManager::DeleteBottle()
const Glib::ustring& BottleManager::GetErrorMessage()
{
std::lock_guard<std::mutex> lock(m_Mutex);
return error_message;
return m_error_message;
}
/**
......@@ -300,7 +305,7 @@ const Glib::ustring& BottleManager::GetErrorMessage()
void BottleManager::RunProgram(string filename, bool is_msi_file)
{
// Check if there is an active bottle set
if(activeBottle != nullptr)
if (activeBottle != nullptr)
{
Glib::ustring wine_prefix = activeBottle->wine_location();
std::thread t(&Helper::RunProgram, wine_prefix, filename, is_msi_file); // false = EXE
......@@ -312,14 +317,27 @@ void BottleManager::RunProgram(string filename, bool is_msi_file)
}
}
/**
* \brief Get the current active bottle name
* \return Bottle name
*/
const Glib::ustring& BottleManager::GetActiveBottleName() {
static const Glib::ustring EMPTY = Glib::ustring("");
if (activeBottle != nullptr) {
return activeBottle->name();
} else {
return EMPTY;
}
}
/**
* \brief Signal handler when the active bottle changes, update active bottle
* \param[in] bottle - New bottle
*/
void BottleManager::SetActiveBottle(BottleItem* bottle)
{
if(bottle != nullptr)
{
if (bottle != nullptr) {
this->activeBottle = bottle;
}
}
......@@ -332,12 +350,10 @@ string BottleManager::GetWineVersion()
{
// Read wine version (is always the same for all bottles atm)
string wineVersion = "";
try
{
try {
wineVersion = Helper::GetWineVersion();
}
catch (const std::runtime_error& error)
{
catch (const std::runtime_error& error) {
mainWindow.ShowErrorMessage(error.what());
}
return wineVersion;
......@@ -349,19 +365,18 @@ string BottleManager::GetWineVersion()
*/
std::map<string, unsigned long> BottleManager::GetBottlePaths()
{
if(!Helper::DirExists(BOTTLE_LOCATION)) {
if (!Helper::DirExists(BOTTLE_LOCATION)) {
// Create directory if not exist yet
if(g_mkdir_with_parents(BOTTLE_LOCATION.c_str(), 0775) < 0 && errno != EEXIST) {
throw std::runtime_error("Failed to create WineGUI directory: " + BOTTLE_LOCATION + " (" + g_strerror(errno) + ")");
if(!Helper::CreateDir(BOTTLE_LOCATION)) {
throw std::runtime_error("Failed to create the Wine bottles directory: " + BOTTLE_LOCATION);
}
}
if(Helper::DirExists(BOTTLE_LOCATION)) {
if (Helper::DirExists(BOTTLE_LOCATION)) {
// Continue
return Helper::GetBottlesPaths(BOTTLE_LOCATION);
}
else
{
throw std::runtime_error("Configuration directory not found (could not create):\n" + BOTTLE_LOCATION);
else {
throw std::runtime_error("Configuration directory still not found (probably no permissions):\n" + BOTTLE_LOCATION);
}
// Otherwise empty
return std::map<string, unsigned long>();
......@@ -408,8 +423,7 @@ std::list<BottleItem> BottleManager::CreateWineBottles(string wineVersion, std::
lastTimeWineUpdated = Helper::GetLastWineUpdated(prefix);
audioDriver = Helper::GetAudioDriver(prefix);
}
catch (const std::runtime_error& error)
{
catch (const std::runtime_error& error) {
mainWindow.ShowErrorMessage(error.what());
}
......
/**
* Copyright (c) 2020 WineGUI
*
* \file settings_window.cc
* \brief Setting GTK+ Window class
* \author Melroy van den Berg <webmaster1989@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "edit_window.h"
#include "bottle_item.h"
/**
* \brief Constructor
* \param parent Reference to parent GTK+ Window
*/
EditWindow::EditWindow(Gtk::Window& parent)
:
edit_button("Edit Configuration"),
delete_button("Delete Machine"),
wine_config_button("WineCfg")
{
set_transient_for(parent);
set_default_size(750, 540);
set_modal(true);
add(settings_grid);
settings_grid.set_margin_top(5);
settings_grid.set_margin_end(5);
settings_grid.set_margin_bottom(8);
settings_grid.set_margin_start(8);
settings_grid.set_column_spacing(8);
settings_grid.set_row_spacing(12);
first_row_label.set_text("WineGUI Settings");
first_row_label.set_xalign(0);
second_row_label.set_text("Other Tools Settings");
second_row_label.set_xalign(0);
first_toolbar.set_toolbar_style(Gtk::ToolbarStyle::TOOLBAR_BOTH);
first_toolbar.set_halign(Gtk::ALIGN_CENTER);
first_toolbar.set_hexpand(true);
second_toolbar.set_toolbar_style(Gtk::ToolbarStyle::TOOLBAR_BOTH);
second_toolbar.set_halign(Gtk::ALIGN_CENTER);
second_toolbar.set_hexpand(true);
settings_grid.attach(first_row_label, 0, 0, 1, 1);
settings_grid.attach(first_toolbar, 0, 1, 1, 1);
settings_grid.attach(second_row_label, 0, 2, 1, 1);
settings_grid.attach(second_toolbar, 0, 3, 1, 1);
// First row with buttons
Gtk::Image* edit_image = Gtk::manage(new Gtk::Image());
edit_image->set_from_icon_name("document-edit", Gtk::IconSize(Gtk::ICON_SIZE_LARGE_TOOLBAR));
edit_button.set_icon_widget(*edit_image);
first_toolbar.insert(edit_button, 0);
Gtk::Image* delete_image = Gtk::manage(new Gtk::Image());
delete_image->set_from_icon_name("edit-delete", Gtk::IconSize(Gtk::ICON_SIZE_LARGE_TOOLBAR));
delete_button.set_icon_widget(*delete_image);
delete_button.set_border_width(2);
first_toolbar.insert(delete_button, 1);
// Second row with buttons
second_toolbar.insert(wine_config_button, 0);
show_all_children();
}
/**
* \brief Destructor
*/
EditWindow::~EditWindow() {}
/**
* \brief Same as show() but will also update the Window title
*/
void EditWindow::Show() {
if (activeBottle != nullptr)
set_title("Edit Machine - " + activeBottle->name());
else
set_title("Edit Machine (Unknown machine)");
// Call parent show
Gtk::Widget::show();
}
/**
* \brief Signal handler when a new bottle is set in the main window
* \param[in] bottle - New bottle
*/
void EditWindow::SetActiveBottle(BottleItem* bottle)
{
this->activeBottle = bottle;
}
/**
* \brief Signal handler for resetting the active bottle to null
*/
void EditWindow::ResetActiveBottle()
{
this->activeBottle = nullptr;
}
\ No newline at end of file
......@@ -108,10 +108,10 @@ std::map<std::string, unsigned long> Helper::GetBottlesPaths(const string& dir_p
std::map<std::string, unsigned long> r;
Glib::Dir dir(dir_path);
auto name = dir.read_name();
while(!name.empty())
while (!name.empty())
{
auto path = Glib::build_filename(dir_path, name);
if(Glib::file_test(path, Glib::FileTest::FILE_TEST_IS_DIR)) {
if (Glib::file_test(path, Glib::FileTest::FILE_TEST_IS_DIR)) {
r.insert(std::pair<string, unsigned long>(path, GetModifiedTime(path)));
}
name = dir.read_name();
......@@ -128,7 +128,7 @@ std::map<std::string, unsigned long> Helper::GetBottlesPaths(const string& dir_p
void Helper::RunProgram(string prefix_path, string program, bool is_msi_file)
{
string msi = "";
if(is_msi_file) {
if (is_msi_file) {
msi = " msiexec /i";
}
// Ignore result of Exec()
......@@ -142,9 +142,9 @@ void Helper::RunProgram(string prefix_path, string program, bool is_msi_file)
string Helper::GetWineVersion()
{
string result = Exec((WINE_EXECUTABLE + " --version").c_str());
if(!result.empty()) {
if (!result.empty()) {
std::vector<string> results = Split(result, '-');
if(results.size() >= 2) {
if (results.size() >= 2) {
string result = results.at(1);;
// Remove new lines
result.erase(std::remove(result.begin(), result.end(), '\n'), result.end());
......@@ -165,7 +165,7 @@ string Helper::GetWineVersion()
void Helper::CreateWineBottle(const string prefix_path, BottleTypes::Bit bit)
{
string winearch = "";
switch(bit) {
switch (bit) {
case BottleTypes::Bit::win32:
winearch = " WINEARCH=win32";
break;
......@@ -175,11 +175,11 @@ void Helper::CreateWineBottle(const string prefix_path, BottleTypes::Bit bit)
}
string result = Exec(("WINEPREFIX=\"" + prefix_path + "\"" + winearch + " " +
WINE_EXECUTABLE + " wineboot>/dev/null 2>&1; echo $?").c_str());
if(!result.empty())
if (!result.empty())
{
// Remove new lines
result.erase(std::remove(result.begin(), result.end(), '\n'), result.end());
if(!(result.compare("0") == 0))
if (!(result.compare("0") == 0))
{
throw std::runtime_error("Something went wrong when creating a new Windows machine. Wine machine: " +
GetName(prefix_path) +
......@@ -199,14 +199,14 @@ void Helper::CreateWineBottle(const string prefix_path, BottleTypes::Bit bit)
*/
void Helper::RemoveWineBottle(const string prefix_path)
{
if(Helper::DirExists(prefix_path))
if (Helper::DirExists(prefix_path))
{
string result = Exec