Skip to content

Commit

Permalink
Make Qiqqa Base Path changeable in the "login"==startup dialog; for s…
Browse files Browse the repository at this point in the history
…afety also ensure the code 'locks' the configured path after this (or before you do anything with it, like backup or restore a qiqqa backup!) so any later change (which should never happen anyway) is immediately flagged as a fatal program failure.

Also DO NOT display any GDI+ failures any more: those originate in SORAX and XULrunner and are unresolvable anyway; those are all display failures which are harmless to the database itself and the large user facing error report dialogs are only highly obnoxious.
  • Loading branch information
GerHobbelt committed Jan 13, 2021
1 parent ecf6c3c commit fd9136a
Show file tree
Hide file tree
Showing 9 changed files with 152 additions and 52 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ desktop.ini

# experimental dev work
/libs/3rdparty/mupdf/mupdf/
/libs/3rdparty/SOLR/

/docs-src/_meta/HTML standards and designs/
/docs-src/_meta/layouts/
Expand Down
Binary file modified Qiqqa.Build/Packaging/Include/couninst.exe
Binary file not shown.
25 changes: 23 additions & 2 deletions Qiqqa/Common/Configuration/ConfigurationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public static bool IsInitialized
private readonly Lazy<string> __startupDirectoryForQiqqa = new Lazy<string>(() => UnitTestDetector.StartupDirectoryForQiqqa);
public string StartupDirectoryForQiqqa => __startupDirectoryForQiqqa.Value;

private readonly Lazy<string> __BaseDirectoryForQiqqa = new Lazy<string>(() =>
private Lazy<string> __BaseDirectoryForQiqqa = new Lazy<string>(() =>
{
// Command-line parameters override the Registry:
string[] args = Environment.GetCommandLineArgs();
Expand Down Expand Up @@ -138,9 +138,30 @@ public static bool IsInitialized
// If we get here, use the default path
return Path.GetFullPath(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"Quantisle/Qiqqa"));
});
private bool __BaseDirectoryForQiqqaIsFixedFromNowOn = false;
public bool BaseDirectoryForQiqqaIsFixedFromNowOn
{
get => __BaseDirectoryForQiqqaIsFixedFromNowOn;
set
{
__BaseDirectoryForQiqqaIsFixedFromNowOn = true; // doesn't matter what you set 'value' to: we only can turn this lock ON and then it's DONE.
}
}
public string BaseDirectoryForQiqqa
{
get => __BaseDirectoryForQiqqa.Value;
get
{
return __BaseDirectoryForQiqqa.Value;
}
set
{
if (BaseDirectoryForQiqqaIsFixedFromNowOn)
{
throw new AccessViolationException($"Internal Error: Rewriting Qiqqa Base Path to '{value}' after it was locked for writing is indicative of erroneous use of the setter, i.e. setter is useed too late in the game!");
}
__BaseDirectoryForQiqqa = new Lazy<string>(() => Path.GetFullPath(value));
RegistrySettings.Instance.Write(RegistrySettings.BaseDataDirectory, value);
}
}

public string BaseDirectoryForUser
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,6 @@ public static void DisplayException(Exception ex)
throw new OutOfMemoryException("Out of memory", ex);
}

// the garbage collection is not crucial for the functioning of the dialog itself, hence dump it into a worker thread.
SafeThreadPool.QueueUserWorkItem(o =>
{
// Collect all generations of memory.
GC.WaitForPendingFinalizers();
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
});

string useful_text_heading = "Something unexpected has happened, but it's okay. " + ex.Message;
string useful_text_subheading = "You can continue working, but we would appreciate it if you would send us some feedback on what you were doing when this happened.";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -784,7 +784,7 @@ private void UpdateLibraryStatistics_Headers()
{
TextLibraryCount.Text = String.Format("{0} document(s) in this library, {1}",
web_library_detail.Xlibrary?.PDFDocuments_IncludingDeleted_Count ?? 0,
web_library_detail.LastSynced.HasValue ? $"last synced on {web_library_detail.LastSynced.Value.ToString()}" : @"has never been synced yet");
web_library_detail.LastSynced.HasValue ? $"which was last synced on {web_library_detail.LastSynced.Value}" : @"which has never been synced yet");
}

// The wizard stuff
Expand Down
118 changes: 81 additions & 37 deletions Qiqqa/Main/LoginStuff/LoginWindow.xaml
Original file line number Diff line number Diff line change
@@ -1,56 +1,100 @@
<commongui:StandardWindow
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local_gui="clr-namespace:Utilities.GUI;assembly=Utilities"
xmlns:commongui="clr-namespace:Qiqqa.Common.GUI"
xmlns:configgui="clr-namespace:Qiqqa.Common.Configuration"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Qiqqa.Main.LoginStuff.LoginWindow"

SizeToContent="Height"
Width="400"
ShowInTaskbar="True"
ResizeMode="NoResize"
WindowStartupLocation="CenterScreen"
Icon="/Qiqqa;component/Qiqqa.ico"
>
<local_gui:AugmentedBorder Margin="10" >
x:Class="Qiqqa.Main.LoginStuff.LoginWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:commongui="clr-namespace:Qiqqa.Common.GUI"
xmlns:configgui="clr-namespace:Qiqqa.Common.Configuration"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local_gui="clr-namespace:Utilities.GUI;assembly=Utilities"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Width="400"
Icon="/Qiqqa;component/Qiqqa.ico"
ResizeMode="NoResize"
ShowInTaskbar="True"
SizeToContent="Height"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<local_gui:AugmentedBorder Margin="10">
<StackPanel>
<Image Width="211" MinHeight="50" x:Name="ImageQiqqaLogo" Margin="0,10,0,0" HorizontalAlignment="Center" />
<local_gui:AugmentedBorder Margin="10" >
<Image
x:Name="ImageQiqqaLogo"
Width="211"
MinHeight="50"
Margin="0,10,0,0"
HorizontalAlignment="Center" />
<local_gui:AugmentedBorder Margin="10">
<StackPanel Margin="10">
<Button x:Name="ButtonGuest" Height="50" Content="Start Qiqqa (ESC)"/>
<Button
x:Name="ButtonGuest"
Height="50"
Content="Start Qiqqa (ESC)" />
</StackPanel>
</local_gui:AugmentedBorder>
<local_gui:AugmentedInfoBarItemControl Margin="10" Header="Backup/Restore" Collapsed="false">
<StackPanel>
<local_gui:AugmentedInfoBarItemControl
Margin="10"
Collapsed="false"
Header="Qiqqa Base Path">
<StackPanel Margin="5">
<TextBlock
Margin="5,5,5,10"
VerticalAlignment="Center"
TextWrapping="Wrap">
<Run Text="Your Qiqqa Databases are located at:" />
</TextBlock>
<TextBlock
Margin="0,0,0,10"
VerticalAlignment="Center"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap">
<Run
x:Name="ObjQiqqaDatabaseLocation"
FontWeight="Bold"
Text="..."
ToolTip="..." />
</TextBlock>
<DockPanel Margin="5">
<TextBlock TextWrapping="Wrap" VerticalAlignment="Center">
<Run Text="Your Qiqqa Database is located at "/>
<Run FontWeight="Bold" x:Name="ObjQiqqaDatabaseLocation"/>
<Run Text="."/>
</TextBlock>
<Button
x:Name="ButtonChangeBasePath"
Height="20"
Content="Change this path" />
</DockPanel>
</StackPanel>
</local_gui:AugmentedInfoBarItemControl>
<local_gui:AugmentedInfoBarItemControl
Margin="10"
Collapsed="false"
Header="Backup/Restore">
<StackPanel>
<DockPanel Margin="5">
<local_gui:AugmentedButton DockPanel.Dock="Left" Width="100" Height="100" Margin="5,5,20,5" x:Name="ButtonBackup" />
<TextBlock TextWrapping="Wrap" VerticalAlignment="Center">
<Run Text="Press the Backup Button to backup your Qiqqa database to a .qiqqa_backup file. You can then transfer this file to safe storage or to a new computer to restore later."/>
<local_gui:AugmentedButton
x:Name="ButtonBackup"
Width="100"
Height="100"
Margin="5,5,20,5"
DockPanel.Dock="Left" />
<TextBlock VerticalAlignment="Center" TextWrapping="Wrap">
<Run Text="Press the Backup Button to backup your Qiqqa database to a .qiqqa_backup file. You can then transfer this file to safe storage or to a new computer to restore later." />
</TextBlock>
</DockPanel>
<DockPanel Margin="5">
<local_gui:AugmentedButton DockPanel.Dock="Left" Width="100" Height="100" Margin="5,5,20,5" x:Name="ButtonRestore" />
<TextBlock TextWrapping="Wrap" VerticalAlignment="Center">
<Run Text="Press the Restore Button to restore a previous .qiqqa_backup file. Please note that this will overwrite your existing Qiqqa Database, so you may first want to do a Backup of your current Qiqqa Database..."/>
<local_gui:AugmentedButton
x:Name="ButtonRestore"
Width="100"
Height="100"
Margin="5,5,20,5"
DockPanel.Dock="Left" />
<TextBlock VerticalAlignment="Center" TextWrapping="Wrap">
<Run Text="Press the Restore Button to restore a previous .qiqqa_backup file. Please note that this will overwrite your existing Qiqqa Database, so you may first want to do a Backup of your current Qiqqa Database..." />
</TextBlock>
</DockPanel>
</StackPanel>
</local_gui:AugmentedInfoBarItemControl>
<local_gui:AugmentedBorder Margin="5,10,5,5" x:Name="ProgressInfoWrapper" >
<local_gui:AugmentedBorder x:Name="ProgressInfoWrapper" Margin="5,10,5,5">
<StackPanel>
<TextBlock x:Name="ProgressInfo" TextWrapping="Wrap" VerticalAlignment="Center">
<TextBlock
x:Name="ProgressInfo"
VerticalAlignment="Center"
TextWrapping="Wrap">
...
</TextBlock>
</StackPanel>
Expand Down
26 changes: 26 additions & 0 deletions Qiqqa/Main/LoginStuff/LoginWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Windows.Input;
using System.Windows.Media;
using icons;
using Microsoft.WindowsAPICodePack.Dialogs;
using Qiqqa.Backups;
using Qiqqa.Common.Configuration;
using Qiqqa.Common.GUI;
Expand Down Expand Up @@ -56,6 +57,9 @@ public LoginWindow()
ImageQiqqaLogo.Source = Icons.GetAppIcon(Icons.QiqqaLogoSmall);

ObjQiqqaDatabaseLocation.Text = ConfigurationManager.Instance.BaseDirectoryForQiqqa;
ObjQiqqaDatabaseLocation.ToolTip = ConfigurationManager.Instance.BaseDirectoryForQiqqa;

ButtonChangeBasePath.Click += ButtonChangeBasePath_Click;

ButtonRestore.Icon = Icons.GetAppIcon(Icons.Backup);
ButtonRestore.IconWidth = ButtonRestore.IconHeight = 64;
Expand All @@ -77,6 +81,23 @@ public LoginWindow()
KeyDown += LoginWindow_KeyDown;
}

private void ButtonChangeBasePath_Click(object sender, RoutedEventArgs e)
{
using (CommonOpenFileDialog dialog = new CommonOpenFileDialog())
{
dialog.InitialDirectory = ConfigurationManager.Instance.BaseDirectoryForQiqqa;
dialog.IsFolderPicker = true;
if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
{
ConfigurationManager.Instance.BaseDirectoryForQiqqa = dialog.FileName;
ObjQiqqaDatabaseLocation.Text = ConfigurationManager.Instance.BaseDirectoryForQiqqa;
ObjQiqqaDatabaseLocation.ToolTip = ConfigurationManager.Instance.BaseDirectoryForQiqqa;

Logging.Info("The user changed the Qiqqa Base directory to folder: {0}", dialog.FileName);
}
}
}

private void UpdateStatusMessage(string message)
{
ProgressInfoWrapper.Visibility = String.IsNullOrEmpty(message) ? Visibility.Collapsed : Visibility.Visible;
Expand All @@ -99,11 +120,13 @@ private void LoginWindow_Closed(object sender, EventArgs e)

private void ButtonBackup_Click(object sender, RoutedEventArgs e)
{
ConfigurationManager.Instance.BaseDirectoryForQiqqaIsFixedFromNowOn = true;
BackingUp.DoBackup();
}

private void ButtonRestore_Click(object sender, RoutedEventArgs e)
{
ConfigurationManager.Instance.BaseDirectoryForQiqqaIsFixedFromNowOn = true;
BackingUp.DoRestore();
}

Expand Down Expand Up @@ -132,6 +155,7 @@ private void DoGuest()
{
IsEnabled = false;

ConfigurationManager.Instance.BaseDirectoryForQiqqaIsFixedFromNowOn = true;
ConfigurationManager.Instance.ResetConfigurationRecordToGuest();
CloseToContinue();
}
Expand Down Expand Up @@ -162,6 +186,8 @@ private void StartMainApplication()
WPFDoEvents.AssertThisCodeIsRunningInTheUIThread();
WPFDoEvents.SetHourglassCursor();

ConfigurationManager.Instance.BaseDirectoryForQiqqaIsFixedFromNowOn = true;

// Initialise the web browser
try
{
Expand Down
20 changes: 18 additions & 2 deletions Qiqqa/Main/MainEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,7 @@ private static void application_DispatcherUnhandledException(object sender, Disp
private static void RemarkOnException(Exception ex, bool potentially_fatal)
{
Logging.Error(ex, "RemarkOnException.....");

if (!ShutdownableManager.Instance.IsShuttingDown)
{
WPFDoEvents.InvokeInUIThread(() =>
Expand All @@ -441,12 +442,27 @@ private static void RemarkOnException_GUI_THREAD(Exception ex, bool potentially_
try
{
Logging.Error(ex, "RemarkOnException_GUI_THREAD...");
UnhandledExceptionMessageBox.DisplayException(ex);

// the garbage collection is not crucial for the functioning of the dialog itself, hence dump it into a worker thread.
SafeThreadPool.QueueUserWorkItem(o =>
{
// Collect all generations of memory.
GC.WaitForPendingFinalizers();
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);
});

bool isGDIfailureInXULrunner = ex.Message.Contains("A generic error occurred in GDI+");
const int EACCESS = unchecked((int)0x80004005);
if (ex.Message.Contains("A generic error occurred in GDI+") || ex.HResult == EACCESS)
if (isGDIfailureInXULrunner || ex.HResult == EACCESS)
{
potentially_fatal = false;
}

// do NOT display GDI+ errors as they are merely obnoxious and unresolvable anyway:
if (!isGDIfailureInXULrunner)
{
UnhandledExceptionMessageBox.DisplayException(ex);
}
}
catch (Exception ex2)
{
Expand Down
4 changes: 2 additions & 2 deletions Utilities/Misc/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ public class Constants
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
public const string QiqqaDevProjectDir = "W:/Projects/sites/library.visyond.gov/80/lib/tooling/qiqqa/Utilities/";
public const string QiqqaDevSolutionDir = "W:/Projects/sites/library.visyond.gov/80/lib/tooling/qiqqa/";
public const string QiqqaDevTargetDir = "W:/Projects/sites/library.visyond.gov/80/lib/tooling/qiqqa/Utilities/bin/Debug/";
public const string QiqqaDevBuild = "Debug";
public const string QiqqaDevTargetDir = "W:/Projects/sites/library.visyond.gov/80/lib/tooling/qiqqa/Utilities/bin/Release/";
public const string QiqqaDevBuild = "Release";
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// These 4 constants are live-patched by the Pre-build task (Qiqqa.Build/patch_settings_file.js)
#endif
Expand Down

0 comments on commit fd9136a

Please sign in to comment.