summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--comphelper/source/misc/backupfilehelper.cxx160
-rw-r--r--include/comphelper/backupfilehelper.hxx13
-rw-r--r--svx/source/dialog/SafeModeDialog.cxx34
-rw-r--r--svx/source/dialog/SafeModeDialog.hxx2
-rw-r--r--svx/uiconfig/ui/safemodedialog.ui162
5 files changed, 267 insertions, 104 deletions
diff --git a/comphelper/source/misc/backupfilehelper.cxx b/comphelper/source/misc/backupfilehelper.cxx
index 4da90b47f743..dd0af8d6709a 100644
--- a/comphelper/source/misc/backupfilehelper.cxx
+++ b/comphelper/source/misc/backupfilehelper.cxx
@@ -688,7 +688,9 @@ namespace
}
public:
- void createUsingExtensionRegistryEntriesFromXML(const OUString& rUserConfigWorkURL)
+ void createUsingExtensionRegistryEntriesFromXML(
+ const OUString& rUserConfigWorkURL,
+ bool bUser)
{
// This is looked up for 'user' in the user|shared|bundled deployed Extensions,
// only the user ones seem to be able to be de/activated. The ones for user are in
@@ -697,13 +699,15 @@ namespace
// in safe mode by deleting the uno_packages directory and the shared|bundled
// ones by deleting the extensions directory.
const OUString aRegPath("/registry/com.sun.star.comp.deployment.bundle.PackageRegistryBackend/backenddb.xml");
- const OUString aUnoPackagReg(rUserConfigWorkURL + "/uno_packages/cache" + aRegPath);
+ const OUString aExtensionsReg(rUserConfigWorkURL + "/extensions/shared" + aRegPath);
+ const OUString aUnoPackageReg(rUserConfigWorkURL + "/uno_packages/cache" + aRegPath);
+ const OUString aPath(bUser ? aUnoPackageReg : aExtensionsReg);
- if (fileExists(aUnoPackagReg))
+ if (fileExists(aPath))
{
uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext();
uno::Reference< xml::dom::XDocumentBuilder > xBuilder(xml::dom::DocumentBuilder::create(xContext));
- uno::Reference< xml::dom::XDocument > aDocument = xBuilder->parseURI(aUnoPackagReg);
+ uno::Reference< xml::dom::XDocument > aDocument = xBuilder->parseURI(aPath);
if (aDocument.is())
{
@@ -1911,20 +1915,6 @@ namespace comphelper
return bPopPossible;
}
- bool BackupFileHelper::isPopPossibleExtensionInfo()
- {
- bool bPopPossible(false);
-
- if (mbActive && mbExtensions)
- {
- const OUString aPackURL(getPackURL());
-
- bPopPossible = isPopPossible_extensionInfo(aPackURL);
- }
-
- return bPopPossible;
- }
-
bool BackupFileHelper::tryPop()
{
bool bDidPop(false);
@@ -1956,6 +1946,20 @@ namespace comphelper
return bDidPop;
}
+ bool BackupFileHelper::isPopPossibleExtensionInfo()
+ {
+ bool bPopPossible(false);
+
+ if (mbActive && mbExtensions)
+ {
+ const OUString aPackURL(getPackURL());
+
+ bPopPossible = isPopPossible_extensionInfo(aPackURL);
+ }
+
+ return bPopPossible;
+ }
+
bool BackupFileHelper::tryPopExtensionInfo()
{
bool bDidPop(false);
@@ -1983,7 +1987,7 @@ namespace comphelper
// extensions are not loaded from XExtensionManager
class ExtensionInfo aExtensionInfo;
- aExtensionInfo.createUsingExtensionRegistryEntriesFromXML(maUserConfigWorkURL);
+ aExtensionInfo.createUsingExtensionRegistryEntriesFromXML(maUserConfigWorkURL, true);
return aExtensionInfo.areThereEnabledExtensions();
}
@@ -1997,7 +2001,7 @@ namespace comphelper
const ExtensionInfoEntryVector aToBeEnabled;
ExtensionInfoEntryVector aToBeDisabled;
- aCurrentExtensionInfo.createUsingExtensionRegistryEntriesFromXML(maUserConfigWorkURL);
+ aCurrentExtensionInfo.createUsingExtensionRegistryEntriesFromXML(maUserConfigWorkURL, true);
const ExtensionInfoEntryVector& rCurrentVector = aCurrentExtensionInfo.getExtensionInfoEntryVector();
@@ -2012,29 +2016,109 @@ namespace comphelper
ExtensionInfo::changeEnableDisableStateInXML(maUserConfigWorkURL, aToBeEnabled, aToBeDisabled);
}
+ bool BackupFileHelper::isTryDeinstallUserExtensionsPossible()
+ {
+ // check if there are User Extensions installed.
+ class ExtensionInfo aExtensionInfo;
+
+ aExtensionInfo.createUsingExtensionRegistryEntriesFromXML(maUserConfigWorkURL, true);
+
+ return !aExtensionInfo.getExtensionInfoEntryVector().empty();
+ }
+
+ void BackupFileHelper::tryDeinstallUserExtensions()
+ {
+ // delete User Extension installs
+ deleteDirRecursively(maUserConfigWorkURL + "/uno_packages");
+ }
+
+ bool BackupFileHelper::isTryDeinstallAllExtensionsPossible()
+ {
+ // check if there are other Extensions installed (shared|bundled).
+ class ExtensionInfo aExtensionInfo;
+
+ aExtensionInfo.createUsingExtensionRegistryEntriesFromXML(maUserConfigWorkURL, false);
+
+ return !aExtensionInfo.getExtensionInfoEntryVector().empty();
+ }
+
+ void BackupFileHelper::tryDeinstallAllExtensions()
+ {
+ // delete other Extension installs (shared|bundled)
+ deleteDirRecursively(maUserConfigWorkURL + "/extensions");
+ }
+
+ const std::vector< OUString >& BackupFileHelper::getCustomizationDirNames()
+ {
+ static std::vector< OUString > aDirNames;
+
+ if (aDirNames.empty())
+ {
+ aDirNames.push_back("config"); // UI config stuff
+ aDirNames.push_back("registry"); // most of the registry stuff
+ aDirNames.push_back("psprint"); // not really needed, can be abandoned
+ aDirNames.push_back("store"); // not really needed, can be abandoned
+ aDirNames.push_back("temp"); // not really needed, can be abandoned
+ aDirNames.push_back("pack"); // own backup dir
+ }
+
+ return aDirNames;
+ }
+
+ const std::vector< OUString >& BackupFileHelper::getCustomizationFileNames()
+ {
+ static std::vector< OUString > aFileNames;
+
+ if (aFileNames.empty())
+ {
+ aFileNames.push_back("registrymodifications.xcu"); // personal registry stuff
+ }
+
+ return aFileNames;
+ }
+
bool BackupFileHelper::isTryResetCustomizationsPossible()
{
- // return true if not all of the customization selection dirs are deleted
- return
- dirExists(maUserConfigWorkURL + "/config") || // UI config stuff
- dirExists(maUserConfigWorkURL + "/registry") || // most of the registry stuff
- dirExists(maUserConfigWorkURL + "/psprint") || // not really needed, can be abandoned
- dirExists(maUserConfigWorkURL + "/store") || // not really needed, can be abandoned
- dirExists(maUserConfigWorkURL + "/temp") || // not really needed, can be abandoned
- dirExists(maUserConfigWorkURL + "/pack") || // own backup dir
- fileExists(maUserConfigWorkURL + "/registrymodifications.xcu"); // personal registry stuff
+ // return true if not all of the customization selection dirs or files are deleted
+ const std::vector< OUString >& rDirs = getCustomizationDirNames();
+
+ for (const auto& a : rDirs)
+ {
+ if (dirExists(maUserConfigWorkURL + "/" + a))
+ {
+ return true;
+ }
+ }
+
+ const std::vector< OUString >& rFiles = getCustomizationFileNames();
+
+ for (const auto& b : rFiles)
+ {
+ if (fileExists(maUserConfigWorkURL + "/" + b))
+ {
+ return true;
+ }
+ }
+
+ return false;
}
void BackupFileHelper::tryResetCustomizations()
{
// delete all of the customization selection dirs
- deleteDirRecursively(maUserConfigWorkURL + "/config");
- deleteDirRecursively(maUserConfigWorkURL + "/registry");
- deleteDirRecursively(maUserConfigWorkURL + "/psprint");
- deleteDirRecursively(maUserConfigWorkURL + "/store");
- deleteDirRecursively(maUserConfigWorkURL + "/temp");
- deleteDirRecursively(maUserConfigWorkURL + "/pack");
- osl::File::remove(maUserConfigWorkURL + "/registrymodifications.xcu");
+ const std::vector< OUString >& rDirs = getCustomizationDirNames();
+
+ for (const auto& a : rDirs)
+ {
+ deleteDirRecursively(maUserConfigWorkURL + "/" + a);
+ }
+
+ const std::vector< OUString >& rFiles = getCustomizationFileNames();
+
+ for (const auto& b : rFiles)
+ {
+ osl::File::remove(maUserConfigWorkURL + "/" + b);
+ }
}
void BackupFileHelper::tryResetUserProfile()
@@ -2379,7 +2463,7 @@ namespace comphelper
// get current extension info, but from XML config files
ExtensionInfo aCurrentExtensionInfo;
- aCurrentExtensionInfo.createUsingExtensionRegistryEntriesFromXML(maUserConfigWorkURL);
+ aCurrentExtensionInfo.createUsingExtensionRegistryEntriesFromXML(maUserConfigWorkURL, true);
// now we have loaded last_working (aLoadedExtensionInfo) and
// current (aCurrentExtensionInfo) ExtensionInfo and may react on
@@ -2412,7 +2496,7 @@ namespace comphelper
{
aToBeDisabled.push_back(rCurrentInfo);
}
- else if (!bCurrentEnabled && !bLoadedEnabled)
+ else if (!bCurrentEnabled && bLoadedEnabled)
{
aToBeEnabled.push_back(rCurrentInfo);
}
diff --git a/include/comphelper/backupfilehelper.hxx b/include/comphelper/backupfilehelper.hxx
index b8250eed1941..8d2161626af2 100644
--- a/include/comphelper/backupfilehelper.hxx
+++ b/include/comphelper/backupfilehelper.hxx
@@ -17,6 +17,7 @@
#include <osl/file.hxx>
#include <memory>
#include <set>
+#include <vector>
namespace comphelper
{
@@ -156,6 +157,16 @@ namespace comphelper
static bool isTryDisableAllExtensionsPossible();
static void tryDisableAllExtensions();
+ /** Deinstall all User Extensions (installed for User only)
+ */
+ static bool isTryDeinstallUserExtensionsPossible();
+ static void tryDeinstallUserExtensions();
+
+ /** Deinstall all Extensions (user|shared|bundled)
+ */
+ static bool isTryDeinstallAllExtensionsPossible();
+ static void tryDeinstallAllExtensions();
+
/** resets User-Customizations like Settings and UserInterface modifications
*/
static bool isTryResetCustomizationsPossible();
@@ -168,6 +179,8 @@ namespace comphelper
private:
// internal helper methods
static const rtl::OUString getPackURL();
+ static const std::vector< OUString >& getCustomizationDirNames();
+ static const std::vector< OUString >& getCustomizationFileNames();
// file push helpers
bool tryPush_Files(const std::set< OUString >& rDirs, const std::set< std::pair< OUString, OUString > >& rFiles, const OUString& rSourceURL, const OUString& rTargetURL);
diff --git a/svx/source/dialog/SafeModeDialog.cxx b/svx/source/dialog/SafeModeDialog.cxx
index 2782edb26c19..fe337815fde5 100644
--- a/svx/source/dialog/SafeModeDialog.cxx
+++ b/svx/source/dialog/SafeModeDialog.cxx
@@ -40,6 +40,8 @@ SafeModeDialog::SafeModeDialog(vcl::Window* pParent)
mpCBCheckProfilesafeConfig(),
mpCBCheckProfilesafeExtensions(),
mpCBDisableAllExtensions(),
+ mpCBDeinstallUserExtensions(),
+ mpCBDeinstallAllExtensions(),
mpCBResetCustomizations(),
mpCBResetWholeUserProfile(),
@@ -52,6 +54,8 @@ SafeModeDialog::SafeModeDialog(vcl::Window* pParent)
get(mpCBCheckProfilesafeConfig, "check_profilesafe_config");
get(mpCBCheckProfilesafeExtensions, "check_profilesafe_extensions");
get(mpCBDisableAllExtensions, "check_disable_all_extensions");
+ get(mpCBDeinstallUserExtensions, "check_deinstall_user_extensions");
+ get(mpCBDeinstallAllExtensions, "check_deinstall_all_extensions");
get(mpCBResetCustomizations, "check_reset_customizations");
get(mpCBResetWholeUserProfile, "check_reset_whole_userprofile");
@@ -64,6 +68,8 @@ SafeModeDialog::SafeModeDialog(vcl::Window* pParent)
mpCBCheckProfilesafeConfig->SetToggleHdl(LINK(this, SafeModeDialog, CheckBoxHdl));
mpCBCheckProfilesafeExtensions->SetToggleHdl(LINK(this, SafeModeDialog, CheckBoxHdl));
mpCBDisableAllExtensions->SetToggleHdl(LINK(this, SafeModeDialog, CheckBoxHdl));
+ mpCBDeinstallUserExtensions->SetToggleHdl(LINK(this, SafeModeDialog, CheckBoxHdl));
+ mpCBDeinstallAllExtensions->SetToggleHdl(LINK(this, SafeModeDialog, CheckBoxHdl));
mpCBResetCustomizations->SetToggleHdl(LINK(this, SafeModeDialog, CheckBoxHdl));
mpCBResetWholeUserProfile->SetToggleHdl(LINK(this, SafeModeDialog, CheckBoxHdl));
@@ -87,11 +93,23 @@ SafeModeDialog::SafeModeDialog(vcl::Window* pParent)
mpCBDisableAllExtensions->Disable();
}
+ if (!comphelper::BackupFileHelper::isTryDeinstallUserExtensionsPossible())
+ {
+ mpCBDeinstallUserExtensions->Disable();
+ }
+
+ if (!comphelper::BackupFileHelper::isTryDeinstallAllExtensionsPossible())
+ {
+ mpCBDeinstallAllExtensions->Disable();
+ }
+
if (!comphelper::BackupFileHelper::isTryResetCustomizationsPossible())
{
mpCBResetCustomizations->Disable();
}
+ // no disabe of mpCBResetWholeUserProfile, always possible (as last choice)
+
// Set URL for help button (module=safemode)
OUString sURL("http://hub.libreoffice.org/send-feedback/?LOversion=" + utl::ConfigManager::getAboutBoxProductVersion() +
"&LOlocale=" + utl::ConfigManager::getLocale() + "&LOmodule=safemode");
@@ -112,6 +130,8 @@ void SafeModeDialog::dispose()
mpCBCheckProfilesafeConfig.clear();
mpCBCheckProfilesafeExtensions.clear();
mpCBDisableAllExtensions.clear();
+ mpCBDeinstallUserExtensions.clear();
+ mpCBDeinstallAllExtensions.clear();
mpCBResetCustomizations.clear();
mpCBResetWholeUserProfile.clear();
@@ -150,6 +170,18 @@ void SafeModeDialog::applyChanges()
comphelper::BackupFileHelper::tryDisableAllExtensions();
}
+ if (mpCBDeinstallUserExtensions->IsChecked())
+ {
+ // Deinstall all User Extensions (installed for User only)
+ comphelper::BackupFileHelper::tryDeinstallUserExtensions();
+ }
+
+ if (mpCBDeinstallAllExtensions->IsChecked())
+ {
+ // Deinstall all Extensions (user|shared|bundled)
+ comphelper::BackupFileHelper::tryDeinstallAllExtensions();
+ }
+
if (mpCBResetCustomizations->IsChecked())
{
// Reset customizations (Settings and UserInterface modifications)
@@ -215,6 +247,8 @@ IMPL_LINK(SafeModeDialog, CheckBoxHdl, CheckBox*, /*pCheckBox*/ )
mpCBCheckProfilesafeConfig->IsChecked() ||
mpCBCheckProfilesafeExtensions->IsChecked() ||
mpCBDisableAllExtensions->IsChecked() ||
+ mpCBDeinstallUserExtensions->IsChecked() ||
+ mpCBDeinstallAllExtensions->IsChecked() ||
mpCBResetCustomizations->IsChecked() ||
mpCBResetWholeUserProfile->IsChecked());
diff --git a/svx/source/dialog/SafeModeDialog.hxx b/svx/source/dialog/SafeModeDialog.hxx
index c1c8d62dbc2b..760573655cf8 100644
--- a/svx/source/dialog/SafeModeDialog.hxx
+++ b/svx/source/dialog/SafeModeDialog.hxx
@@ -39,6 +39,8 @@ private:
VclPtr<CheckBox> mpCBCheckProfilesafeConfig;
VclPtr<CheckBox> mpCBCheckProfilesafeExtensions;
VclPtr<CheckBox> mpCBDisableAllExtensions;
+ VclPtr<CheckBox> mpCBDeinstallUserExtensions;
+ VclPtr<CheckBox> mpCBDeinstallAllExtensions;
VclPtr<CheckBox> mpCBResetCustomizations;
VclPtr<CheckBox> mpCBResetWholeUserProfile;
diff --git a/svx/uiconfig/ui/safemodedialog.ui b/svx/uiconfig/ui/safemodedialog.ui
index cfc7e0fcc568..54bbb1e0c7d7 100644
--- a/svx/uiconfig/ui/safemodedialog.ui
+++ b/svx/uiconfig/ui/safemodedialog.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
+<!-- Generated with glade 3.16.1 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<object class="GtkDialog" id="SafeModeDialog">
@@ -13,71 +13,16 @@
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
- <child internal-child="action_area">
- <object class="GtkButtonBox" id="dialog-action_area1">
- <property name="can_focus">False</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="btn_continue">
- <property name="label" translatable="yes">_Continue in Safe Mode</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_default">True</property>
- <property name="receives_default">True</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="btn_quit">
- <property name="label" translatable="yes">_Quit</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="btn_restart">
- <property name="label" translatable="yes">_Make Changes and Restart</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">3</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="pack_type">end</property>
- <property name="position">4</property>
- </packing>
- </child>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
<property name="label" translatable="yes">%PRODUCTNAME is now running in Safe Mode. You can make one or more of the following changes to return to a working state.
The offered possible changes get more radical from top to bottom, so it is recommended to try them thoroughly one after the other.</property>
<property name="wrap">True</property>
- <property name="xalign">0</property>
- <property name="yalign">0</property>
</object>
<packing>
<property name="expand">False</property>
@@ -92,7 +37,7 @@ The offered possible changes get more radical from top to bottom, so it is recom
<property name="orientation">vertical</property>
<child>
<object class="GtkCheckButton" id="check_profilesafe_config">
- <property name="label" translatable="yes">Reset UserConfiguration to last known working state</property>
+ <property name="label" translatable="yes">Restore UserConfiguration to last known working state from backup</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
@@ -107,7 +52,7 @@ The offered possible changes get more radical from top to bottom, so it is recom
</child>
<child>
<object class="GtkCheckButton" id="check_profilesafe_extensions">
- <property name="label" translatable="yes">Reset State of installed Extensions to last known working state</property>
+ <property name="label" translatable="yes">Restore enable/disable State of installed User Extensions to last known working state</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
@@ -122,7 +67,7 @@ The offered possible changes get more radical from top to bottom, so it is recom
</child>
<child>
<object class="GtkCheckButton" id="check_disable_all_extensions">
- <property name="label" translatable="yes">Disable all extensions</property>
+ <property name="label" translatable="yes">Disable all User Extensions</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
@@ -136,8 +81,8 @@ The offered possible changes get more radical from top to bottom, so it is recom
</packing>
</child>
<child>
- <object class="GtkCheckButton" id="check_reset_customizations">
- <property name="label" translatable="yes">Reset customizations (Settings and User Interface modifications)</property>
+ <object class="GtkCheckButton" id="check_deinstall_user_extensions">
+ <property name="label" translatable="yes">Deinstall all User Extensions</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
@@ -151,8 +96,8 @@ The offered possible changes get more radical from top to bottom, so it is recom
</packing>
</child>
<child>
- <object class="GtkCheckButton" id="check_reset_whole_userprofile">
- <property name="label" translatable="yes">Reset the whole User Profile</property>
+ <object class="GtkCheckButton" id="check_deinstall_all_extensions">
+ <property name="label" translatable="yes">Deinstall all Extensions (including shared and bundled)</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
@@ -165,6 +110,36 @@ The offered possible changes get more radical from top to bottom, so it is recom
<property name="position">4</property>
</packing>
</child>
+ <child>
+ <object class="GtkCheckButton" id="check_reset_customizations">
+ <property name="label" translatable="yes">Reset User Customizations (Settings, User Interface modifications, AutoCorrect, AutoText, etc.)</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">5</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="check_reset_whole_userprofile">
+ <property name="label" translatable="yes">Reset the whole User Profile to initial state after Installation</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">6</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="expand">False</property>
@@ -186,10 +161,10 @@ The offered possible changes get more radical from top to bottom, so it is recom
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="xalign">0</property>
<property name="label" translatable="yes">If you experience problems that are not resolved by using the Safe Mode, visit the following link to get help or report a bug.
You can also include the relevant parts of your User Profile. Beware that it might contain personal data.</property>
- <property name="xalign">0</property>
</object>
<packing>
<property name="expand">False</property>
@@ -228,6 +203,61 @@ You can also include the relevant parts of your User Profile. Beware that it mig
<property name="position">3</property>
</packing>
</child>
+ <child internal-child="action_area">
+ <object class="GtkButtonBox" id="dialog-action_area1">
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="btn_continue">
+ <property name="label" translatable="yes">_Continue in Safe Mode</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_default">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="btn_quit">
+ <property name="label" translatable="yes">_Quit</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="btn_restart">
+ <property name="label" translatable="yes">_Make Changes and Restart</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_underline">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="pack_type">end</property>
+ <property name="position">4</property>
+ </packing>
+ </child>
</object>
</child>
</object>