in tools/Explorer/ViewModels/ViewModel.cs [452:962]
public ViewModel(MainWindow view, Model model)
{
this.view = view;
this.model = model;
model.DatabaseChanging += (databaseName) => {
this.Status = $"Opening database {databaseName}...";
};
model.DatabaseChanged += (databaseName) => {
this.Status = "";
};
// Take care of events bubbling up from the model.
model.PropertyChanged += (object sender, PropertyChangedEventArgs e) =>
{
if (e.PropertyName == "CaretPositionString")
{
this.CaretPositionString = model.CaretPositionString;
}
else if (e.PropertyName == "Status")
{
this.Status = model.Status;
}
else if (e.PropertyName == "Databases")
{
this.Databases = model.Databases;
}
else if (e.PropertyName == "SelectedDatabase")
{
this.SelectedDatabase = model.SelectedDatabase;
this.UpdateConnectionInfo();
}
else if (e.PropertyName == "QueryResult")
{
this.QueryResult = model.QueryResult;
}
else if (e.PropertyName == "Username" || e.PropertyName == "HostName" || e.PropertyName == "SelectedDatabase")
{
this.UpdateConnectionInfo();
}
else
{
throw new ArgumentException("Property " + e.PropertyName + " was not handled");
}
};
this.AboutBoxCommand = new RelayCommand(
p =>
{
var aboutBox = new Views.AboutBox();
aboutBox.Show();
}
);
this.XQueryHelpCommand = new RelayCommand(
p =>
{
var psi = new ProcessStartInfo
{
FileName = "https://www.w3.org/standards/xml/query",
UseShellExecute = true
};
Process.Start(psi);
}
);
this.BaseXHelpCommand = new RelayCommand(
p =>
{
var psi = new ProcessStartInfo
{
FileName = "http://BaseX.org",
UseShellExecute = true
};
Process.Start(psi);
}
);
this.ShowExternalVariablesDialogCommand = new RelayCommand(
p =>
{
var window = new ExternalVariablesControl();
window.ShowDialog();
}
);
this.SaveResultsCommand = new RelayCommand(
p =>
{
var dialog = new SaveFileDialog
{
DefaultExt = ".xml",
AddExtension = true,
Filter = "XML files (*.xml)|*.xml|CSV (Comma delimited) (*.csv)|*.csv|All files (*.*)|*.*",
};
var documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
dialog.InitialDirectory = string.Format(Properties.Settings.Default.QueriesPath, documentsFolder);
bool? res = dialog.ShowDialog();
if (res.HasValue && res.Value)
{
var stream = dialog.OpenFile();
this.view.ResultsEditor.Save(stream);
}
}
);
this.OpenQueryCommand = new RelayCommand(
p =>
{
this.OpenQueryFile();
}
);
this.ExitApplicationCommand = new RelayCommand(
p => {
this.view.Close();
});
this.KeyboardExecuteQueryCommand = new RelayCommand(
p =>
{
var item = view.queryTabPage.SelectedItem as Wpf.Controls.TabItem;
this.ExecuteQueryCommand.Execute(item.Content);
},
p =>
{
var item = view.queryTabPage.SelectedItem as Wpf.Controls.TabItem;
return this.ExecuteQueryCommand.CanExecute(item.Content);
});
this.KeyboardCheckQueryCommand = new RelayCommand(
p =>
{
var item = view.queryTabPage.SelectedItem as Wpf.Controls.TabItem;
this.CheckQueryCommand.Execute(item.Content);
},
p =>
{
var item = view.queryTabPage.SelectedItem as Wpf.Controls.TabItem;
return this.CheckQueryCommand.CanExecute(item.Content);
});
this.WindowsCommand = new RelayCommand(
p =>
{
this.OpenWindowsDialog();
},
p => { return true; }
);
this.CloseAllWindowsCommand = new RelayCommand(
p =>
{
this.view.DetailsTab.Items.Clear();
},
p => this.view.DetailsTab.Items.Count > 0
);
this.SaveCommand = new RelayCommand(
p => // The parameter is the index of the selected tab
{
var tab = view.queryTabPage.SelectedValue as Wpf.Controls.TabItem;
var editor = tab.Content as QueryEditor;
if (string.IsNullOrEmpty(tab.Tag as string))
{
var filename = SaveQueryFileAs(editor);
if (filename != null)
{
// The user entered a file, he did not cancel
tab.Tag = filename;
// Update the tab's title
tab.Title = Path.GetFileNameWithoutExtension(filename);
// Remove dirty indication
editor.IsModified = false;
}
}
else
{
SaveQueryFile(tab.Tag as string, editor);
editor.IsModified = false;
}
},
p =>
{
return true;
}
);
this.SaveAsCommand = new RelayCommand(
p => // The parameter is the index of the selected tab
{
var tab = view.queryTabPage.SelectedValue as Wpf.Controls.TabItem;
var editor = tab.Content as QueryEditor;
var filename = SaveQueryFileAs(editor);
if (filename != null)
{
tab.Tag = filename;
// Update the tab's title
tab.Title = Path.GetFileNameWithoutExtension(filename);
editor.IsModified = false;
}
},
p =>
{
return true;
}
);
this.CreateNewQueryCommand = new RelayCommand(
p =>
{
this.view.queryTabPage.SelectedItem = this.CreateNewQueryTabItem();
}
);
this.OpenQueuedQueriesWindow = new RelayCommand(
p =>
{
// Open the queued queries window. This is a singleton
this.QueuedQueriesWindow.Show();
this.QueuedQueriesWindow.Activate();
});
this.IncreaseResultsFontSizeCommand = new RelayCommand(
p1 => Properties.Settings.Default.ResultsFontSize += 2,
p2 => this.view.ResultsEditor != null && this.view.ResultsEditor.FontSize < 48
);
this.DecreaseResultsFontSizeCommand = new RelayCommand(
p1 => Properties.Settings.Default.ResultsFontSize -= 2,
p2 => this.view.ResultsEditor != null && this.view.ResultsEditor.FontSize > 8
);
this.IncreaseQueryFontSizeCommand = new RelayCommand(
p1 => Properties.Settings.Default.QueryFontSize += 2,
p2 =>
{
if (this.view.queryTabPage == null)
return false;
else
{
return this.view.queryTabPage.SelectedContent is QueryEditor queryEditor && queryEditor.FontSize < 48;
}
});
this.DecreaseQueryFontSizeCommand = new RelayCommand(
p1 => Properties.Settings.Default.QueryFontSize -= 2,
p2 =>
{
if (this.view.queryTabPage == null)
return false;
else
{
return this.view.queryTabPage.SelectedContent is QueryEditor queryEditor && queryEditor.FontSize > 8;
}
}
);
this.ResultsUndoCommand = new RelayCommand(
p =>
{
ResultsEditor editor = p as ResultsEditor;
editor.Undo();
},
p =>
{
if (p is ResultsEditor editor)
return editor.CanUndo;
else
return false;
}
);
this.ResultsRedoCommand = new RelayCommand(
p =>
{
ResultsEditor editor = p as ResultsEditor;
editor.Redo();
},
p =>
{
if (p is ResultsEditor editor)
return editor.CanRedo;
else
return false;
}
);
this.QueryUndoCommand = new RelayCommand(
p =>
{
QueryEditor editor = p as QueryEditor;
editor.Undo();
},
p =>
{
if (p is QueryEditor editor)
return editor.CanUndo;
else
return false;
}
);
this.QueryRedoCommand = new RelayCommand(
p =>
{
QueryEditor editor = p as QueryEditor;
editor.Redo();
},
p =>
{
if (p is QueryEditor editor)
return editor.CanRedo;
else
return false;
}
);
this.ExecuteQueryCommand = new RelayCommand(
async p =>
{
var queryEditor = p as QueryEditor;
string query;
if (queryEditor.SelectionLength > 0)
{
// The user selected some text, so use that as the query.
query = queryEditor.SelectedText;
}
else
{
// No selection, so assume whole editor content
query = queryEditor.Text;
}
string result;
Stopwatch queryExecutionTime = new Stopwatch();
queryExecutionTime.Start();
var tabItem = queryEditor.Parent as Wpf.Controls.TabItem;
using (var session = await model.Server.GetSessionAsync(this.model.SelectedDatabase.Name))
{
try
{
tabItem.Icon = new Image
{
Source = new BitmapImage(new Uri("images/Hourglass_16x.png", UriKind.Relative)),
Width = 16,
Height = 16,
};
result = await this.ExecuteQueryAsync(query, session);
}
catch (Exception e)
{
result = e.Message;
}
finally
{
tabItem.Icon = null;
}
}
queryExecutionTime.Stop();
// Log the result in the QueryResult so we can select it again if the
// user comes back to the query editor.
this.CachedQueryResult[queryEditor] = result;
#if !NETCOREAPP
// Log the fact that a query has been evaluated to telemetry.
(Application.Current as App).Telemetry?.TrackEvent(
"QueryExecution", new Dictionary<string, string>()
{
["Query"] = query,
["ExecutionTime"] = queryExecutionTime.ElapsedMilliseconds.ToString()
}
);
#endif
this.model.QueryResult = result;
},
// Running is allowed when there is text there to submit as a query and
// there is a connection to the database.
p =>
{
if (p is QueryEditor queryEditor)
return (queryEditor.Text.Length > 0) && this.SelectedDatabase != null && !string.IsNullOrEmpty(this.SelectedDatabase.Name);
else
return false;
});
this.CheckQueryCommand = new RelayCommand(
async p =>
{
var queryEditor = p as QueryEditor;
string query;
if (queryEditor.SelectionLength > 0)
{
// The user selected some text, so use that as the query.
query = queryEditor.SelectedText;
}
else
{
// No selection, so assume whole editor content
query = queryEditor.Text;
}
string result;
Stopwatch queryCheckTime = new Stopwatch();
queryCheckTime.Start();
using (var session = await model.Server.GetSessionAsync(this.model.SelectedDatabase.Name))
{
try
{
result = await session.CheckQueryAsync(query);
}
catch (Exception e)
{
result = e.Message;
}
}
queryCheckTime.Stop();
// Log the result in the QueryResult so we can select it again if the
// user comes back to the query editor.
this.CachedQueryResult[queryEditor] = result;
#if !NETCOREAPP
// Log the fact that a query has been evaluated to telemetry.
(Application.Current as App).Telemetry?.TrackEvent(
"CheckQuery", new Dictionary<string, string>()
{
["Query"] = query,
["ExecutionTime"] = queryCheckTime.ElapsedMilliseconds.ToString()
}
);
#endif
this.model.QueryResult = result;
},
// Running is allowed when there is text there to submit as a query and
// there is a connection to the database.
p =>
{
if (p is QueryEditor queryEditor)
return (queryEditor.Text.Length > 0) && this.SelectedDatabase != null && !string.IsNullOrEmpty(this.SelectedDatabase.Name);
else
return false;
});
this.SubmitQueryCommand = new RelayCommand(
async p =>
{
var queryEditor = p as QueryEditor;
string query;
if (queryEditor.SelectionLength > 0)
{
// The user selected some text, so use that as the query.
query = queryEditor.SelectedText;
}
else
{
// No selection, so assume whole editor content
query = queryEditor.Text;
}
string result;
try
{
using var session = await this.model.GetSessionAsync(this.model.SelectedDatabase.Name);
result = await session.SubmitQueryAsync(query);
}
catch (Exception e)
{
result = e.Message;
}
this.model.JobIdToQuery[result] = query;
this.model.QueryResult = result;
},
// Running is allowed when there is text there to submit as a query and
// there is a connection to the database.
p =>
{
if (p is QueryEditor queryEditor)
return (queryEditor.Text.Length > 0);
else
return false;
});
}