436c879b35
Change-Id: I91d70d72ea6cb18ed4fde2f3b3a3d037668767e5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152615 Tested-by: Jenkins Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
367 lines
14 KiB
C++
367 lines
14 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "gtv-application-window.hxx"
|
|
#include "gtv-main-toolbar.hxx"
|
|
#include "gtv-signal-handlers.hxx"
|
|
#include "gtv-helpers.hxx"
|
|
|
|
#include <LibreOfficeKit/LibreOfficeKitGtk.h>
|
|
|
|
#include <algorithm>
|
|
#include <fstream>
|
|
#include <map>
|
|
#include <memory>
|
|
|
|
namespace {
|
|
|
|
struct GtvMainToolbarPrivateImpl
|
|
{
|
|
GtkWidget* toolbar1;
|
|
GtkWidget* toolbar2;
|
|
|
|
GtkWidget* m_pEnableEditing;
|
|
GtkWidget* m_pLeftpara;
|
|
GtkWidget* m_pCenterpara;
|
|
GtkWidget* m_pRightpara;
|
|
GtkWidget* m_pJustifypara;
|
|
GtkWidget* m_pDeleteComment;
|
|
GtkWidget* m_pPartSelector;
|
|
GtkWidget* m_pPartModeSelector;
|
|
GtkWidget* m_pRecentUnoSelector;
|
|
std::map<std::string, std::string> m_pRecentUnoCommands;
|
|
|
|
/// Sensitivity (enabled or disabled) for each tool item, ignoring edit state
|
|
std::map<GtkToolItem*, bool> m_aToolItemSensitivities;
|
|
|
|
GtvMainToolbarPrivateImpl() :
|
|
toolbar1(nullptr),
|
|
toolbar2(nullptr),
|
|
m_pEnableEditing(nullptr),
|
|
m_pLeftpara(nullptr),
|
|
m_pCenterpara(nullptr),
|
|
m_pRightpara(nullptr),
|
|
m_pJustifypara(nullptr),
|
|
m_pDeleteComment(nullptr),
|
|
m_pPartSelector(nullptr),
|
|
m_pPartModeSelector(nullptr),
|
|
m_pRecentUnoSelector(nullptr)
|
|
{ }
|
|
};
|
|
|
|
struct GtvMainToolbarPrivate
|
|
{
|
|
GtvMainToolbarPrivateImpl* m_pImpl;
|
|
|
|
GtvMainToolbarPrivateImpl* operator->()
|
|
{
|
|
return m_pImpl;
|
|
}
|
|
};
|
|
|
|
}
|
|
|
|
#if defined __clang__
|
|
#if __has_warning("-Wdeprecated-volatile")
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wdeprecated-volatile"
|
|
#endif
|
|
#endif
|
|
G_DEFINE_TYPE_WITH_PRIVATE(GtvMainToolbar, gtv_main_toolbar, GTK_TYPE_BOX);
|
|
#if defined __clang__
|
|
#if __has_warning("-Wdeprecated-volatile")
|
|
#pragma clang diagnostic pop
|
|
#endif
|
|
#endif
|
|
|
|
static GtvMainToolbarPrivate&
|
|
getPrivate(GtvMainToolbar* toolbar)
|
|
{
|
|
return *static_cast<GtvMainToolbarPrivate*>(gtv_main_toolbar_get_instance_private(toolbar));
|
|
}
|
|
|
|
static void
|
|
gtv_main_toolbar_init(GtvMainToolbar* toolbar)
|
|
{
|
|
GtvMainToolbarPrivate& priv = getPrivate(toolbar);
|
|
priv.m_pImpl = new GtvMainToolbarPrivateImpl();
|
|
|
|
const std::string uiFilePath = GtvHelpers::getDirPath(__FILE__) + std::string(UI_FILE_NAME);
|
|
GtvGtkWrapper<GtkBuilder> builder(gtk_builder_new_from_file(uiFilePath.c_str()),
|
|
[](GtkBuilder* pBuilder) {
|
|
g_object_unref(pBuilder);
|
|
});
|
|
|
|
priv->toolbar1 = GTK_WIDGET(gtk_builder_get_object(builder.get(), "toolbar1"));
|
|
gtk_box_pack_start(GTK_BOX(toolbar), priv->toolbar1, false, false, false);
|
|
priv->toolbar2 = GTK_WIDGET(gtk_builder_get_object(builder.get(), "toolbar2"));
|
|
gtk_box_pack_start(GTK_BOX(toolbar), priv->toolbar2, false, false, false);
|
|
|
|
priv->m_pEnableEditing = GTK_WIDGET(gtk_builder_get_object(builder.get(), "btn_editmode"));
|
|
priv->m_pLeftpara = GTK_WIDGET(gtk_builder_get_object(builder.get(), "btn_justifyleft"));
|
|
priv->m_pCenterpara = GTK_WIDGET(gtk_builder_get_object(builder.get(), "btn_justifycenter"));
|
|
priv->m_pRightpara = GTK_WIDGET(gtk_builder_get_object(builder.get(), "btn_justifyright"));
|
|
priv->m_pJustifypara = GTK_WIDGET(gtk_builder_get_object(builder.get(), "btn_justifyfill"));
|
|
priv->m_pDeleteComment = GTK_WIDGET(gtk_builder_get_object(builder.get(), "btn_removeannotation"));
|
|
priv->m_pPartSelector = GTK_WIDGET(gtk_builder_get_object(builder.get(), "combo_partselector"));
|
|
priv->m_pPartModeSelector = GTK_WIDGET(gtk_builder_get_object(builder.get(), "combo_partsmodeselector"));
|
|
priv->m_pRecentUnoSelector = GTK_WIDGET(gtk_builder_get_object(builder.get(), "combo_recentunoselector"));
|
|
|
|
toolbar->m_pAddressbar = GTK_WIDGET(gtk_builder_get_object(builder.get(), "addressbar_entry"));
|
|
toolbar->m_pFormulabar = GTK_WIDGET(gtk_builder_get_object(builder.get(), "formulabar_entry"));
|
|
toolbar->m_pContentControlSelector
|
|
= GTK_WIDGET(gtk_builder_get_object(builder.get(), "combo_contentcontrolselector"));
|
|
toolbar->m_pContentControlDateSelector
|
|
= GTK_WIDGET(gtk_builder_get_object(builder.get(), "menu_contentcontroldateselector"));
|
|
|
|
// TODO: compile with -rdynamic and get rid of it
|
|
gtk_builder_add_callback_symbol(builder.get(), "btn_clicked", G_CALLBACK(btn_clicked));
|
|
gtk_builder_add_callback_symbol(builder.get(), "doCopy", G_CALLBACK(doCopy));
|
|
gtk_builder_add_callback_symbol(builder.get(), "doPaste", G_CALLBACK(doPaste));
|
|
gtk_builder_add_callback_symbol(builder.get(), "createView", G_CALLBACK(createView));
|
|
gtk_builder_add_callback_symbol(builder.get(), "getRulerState", G_CALLBACK(getRulerState));
|
|
gtk_builder_add_callback_symbol(builder.get(), "recentUnoChanged", G_CALLBACK(recentUnoChanged));
|
|
gtk_builder_add_callback_symbol(builder.get(), "unoCommandDebugger", G_CALLBACK(unoCommandDebugger));
|
|
gtk_builder_add_callback_symbol(builder.get(), "commandValuesDebugger", G_CALLBACK(commandValuesDebugger));
|
|
gtk_builder_add_callback_symbol(builder.get(), "toggleEditing", G_CALLBACK(toggleEditing));
|
|
gtk_builder_add_callback_symbol(builder.get(), "changePartMode", G_CALLBACK(changePartMode));
|
|
gtk_builder_add_callback_symbol(builder.get(), "changePart", G_CALLBACK(changePart));
|
|
gtk_builder_add_callback_symbol(builder.get(), "changeContentControl",
|
|
G_CALLBACK(changeContentControl));
|
|
gtk_builder_add_callback_symbol(builder.get(), "changeDateContentControl",
|
|
G_CALLBACK(changeDateContentControl));
|
|
gtk_builder_add_callback_symbol(builder.get(), "changeZoom", G_CALLBACK(changeZoom));
|
|
gtk_builder_add_callback_symbol(builder.get(), "toggleFindbar", G_CALLBACK(toggleFindbar));
|
|
gtk_builder_add_callback_symbol(builder.get(), "documentRedline", G_CALLBACK(documentRedline));
|
|
gtk_builder_add_callback_symbol(builder.get(), "documentRepair", G_CALLBACK(documentRepair));
|
|
gtk_builder_add_callback_symbol(builder.get(), "signalAddressbar", G_CALLBACK(signalAddressbar));
|
|
gtk_builder_add_callback_symbol(builder.get(), "signalFormulabar", G_CALLBACK(signalFormulabar));
|
|
|
|
// find toolbar
|
|
// Note: These buttons are not the part of GtvMainToolbar
|
|
gtk_builder_add_callback_symbol(builder.get(), "signalSearchNext", G_CALLBACK(signalSearchNext));
|
|
gtk_builder_add_callback_symbol(builder.get(), "signalSearchPrev", G_CALLBACK(signalSearchPrev));
|
|
gtk_builder_add_callback_symbol(builder.get(), "signalFindbar", G_CALLBACK(signalFindbar));
|
|
gtk_builder_add_callback_symbol(builder.get(), "toggleFindAll", G_CALLBACK(toggleFindAll));
|
|
|
|
gtk_builder_connect_signals(builder.get(), nullptr);
|
|
|
|
gtk_widget_show_all(GTK_WIDGET(toolbar));
|
|
}
|
|
|
|
static void
|
|
gtv_main_toolbar_finalize(GObject* object)
|
|
{
|
|
GtvMainToolbarPrivate& priv = getPrivate(GTV_MAIN_TOOLBAR(object));
|
|
|
|
delete priv.m_pImpl;
|
|
priv.m_pImpl = nullptr;
|
|
|
|
G_OBJECT_CLASS (gtv_main_toolbar_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gtv_main_toolbar_class_init(GtvMainToolbarClass* klass)
|
|
{
|
|
G_OBJECT_CLASS(klass)->finalize = gtv_main_toolbar_finalize;
|
|
}
|
|
|
|
static void populatePartSelector(GtvMainToolbar* toolbar)
|
|
{
|
|
GtvMainToolbarPrivate& priv = getPrivate(toolbar);
|
|
GtvApplicationWindow* window = GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(toolbar)));
|
|
gtv_application_window_set_part_broadcast(window, false);
|
|
gtk_list_store_clear( GTK_LIST_STORE(
|
|
gtk_combo_box_get_model(
|
|
GTK_COMBO_BOX(priv->m_pPartSelector) )) );
|
|
|
|
if (!window->lokdocview)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const int nMaxLength = 50;
|
|
char sText[nMaxLength];
|
|
|
|
int nParts = lok_doc_view_get_parts(LOK_DOC_VIEW(window->lokdocview));
|
|
for ( int i = 0; i < nParts; i++ )
|
|
{
|
|
char* pName = lok_doc_view_get_part_name(LOK_DOC_VIEW(window->lokdocview), i);
|
|
assert( pName );
|
|
snprintf( sText, nMaxLength, "%i (%s)", i+1, pName );
|
|
free( pName );
|
|
|
|
gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT(priv->m_pPartSelector), sText );
|
|
}
|
|
gtk_combo_box_set_active(GTK_COMBO_BOX(priv->m_pPartSelector), lok_doc_view_get_part(LOK_DOC_VIEW(window->lokdocview)));
|
|
|
|
gtv_application_window_set_part_broadcast(window, true);
|
|
}
|
|
|
|
static void populateRecentUnoSelector(GtvMainToolbar* toolbar)
|
|
{
|
|
GtvMainToolbarPrivate& priv = getPrivate(toolbar);
|
|
GtkComboBoxText* pSelector = GTK_COMBO_BOX_TEXT(priv->m_pRecentUnoSelector);
|
|
|
|
unsigned counter = 0;
|
|
std::ifstream is("/tmp/gtv-recentunos.txt");
|
|
while (is.good() && counter < 10)
|
|
{
|
|
std::string unoCommandStr;
|
|
std::getline(is, unoCommandStr);
|
|
std::vector<std::string> aUnoCmd = GtvHelpers::split<std::string>(unoCommandStr, " | ", 2);
|
|
if (aUnoCmd.size() != 2)
|
|
continue;
|
|
auto it = priv->m_pRecentUnoCommands.emplace(aUnoCmd[0], aUnoCmd[1]);
|
|
if (it.second)
|
|
{
|
|
gtk_combo_box_text_append_text(pSelector, aUnoCmd[0].c_str());
|
|
++counter;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
gtv_main_toolbar_doc_loaded(GtvMainToolbar* toolbar, LibreOfficeKitDocumentType eDocType, bool bEditMode)
|
|
{
|
|
GtvMainToolbarPrivate& priv = getPrivate(toolbar);
|
|
gtk_widget_set_visible(toolbar->m_pAddressbar, false);
|
|
gtk_widget_set_visible(toolbar->m_pFormulabar, false);
|
|
if (eDocType == LOK_DOCTYPE_SPREADSHEET)
|
|
{
|
|
gtk_tool_button_set_label(GTK_TOOL_BUTTON(priv->m_pLeftpara), ".uno:AlignLeft");
|
|
gtk_tool_button_set_label(GTK_TOOL_BUTTON(priv->m_pCenterpara), ".uno:AlignHorizontalCenter");
|
|
gtk_tool_button_set_label(GTK_TOOL_BUTTON(priv->m_pRightpara), ".uno:AlignRight");
|
|
gtk_widget_hide(priv->m_pJustifypara);
|
|
gtk_tool_button_set_label(GTK_TOOL_BUTTON(priv->m_pDeleteComment), ".uno:DeleteNote");
|
|
|
|
gtk_widget_set_visible(toolbar->m_pAddressbar, true);
|
|
gtk_widget_set_visible(toolbar->m_pFormulabar, true);
|
|
}
|
|
else if (eDocType == LOK_DOCTYPE_PRESENTATION)
|
|
{
|
|
gtk_tool_button_set_label(GTK_TOOL_BUTTON(priv->m_pDeleteComment), ".uno:DeleteAnnotation");
|
|
}
|
|
|
|
gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv->m_pEnableEditing), bEditMode);
|
|
|
|
// populate combo boxes
|
|
populatePartSelector(toolbar);
|
|
|
|
// populate recent uno selector
|
|
populateRecentUnoSelector(toolbar);
|
|
}
|
|
|
|
void
|
|
gtv_main_toolbar_add_recent_uno(GtvMainToolbar* toolbar, const std::string& rUnoCmdStr)
|
|
{
|
|
GtvMainToolbarPrivate& priv = getPrivate(toolbar);
|
|
GtkComboBoxText* pSelector = GTK_COMBO_BOX_TEXT(priv->m_pRecentUnoSelector);
|
|
|
|
const std::vector<std::string> aUnoCmd = GtvHelpers::split<std::string>(rUnoCmdStr, " | ", 2);
|
|
priv->m_pRecentUnoCommands[aUnoCmd[0]] = aUnoCmd[1];
|
|
// keep placeholder string at the top
|
|
gtk_combo_box_text_insert_text(pSelector, 1, aUnoCmd[0].c_str());
|
|
// TODO: Remove other text entries with same key
|
|
}
|
|
|
|
std::string
|
|
gtv_main_toolbar_get_recent_uno_args(GtvMainToolbar* toolbar, const std::string& rUnoCmd)
|
|
{
|
|
GtvMainToolbarPrivate& priv = getPrivate(toolbar);
|
|
auto it = std::find_if(priv->m_pRecentUnoCommands.begin(), priv->m_pRecentUnoCommands.end(),
|
|
[&rUnoCmd](const std::pair<std::string, std::string>& pair) {
|
|
return rUnoCmd == pair.first;
|
|
});
|
|
std::string ret;
|
|
if (it != priv->m_pRecentUnoCommands.end())
|
|
ret = it->second;
|
|
return ret;
|
|
}
|
|
|
|
GtkContainer*
|
|
gtv_main_toolbar_get_first_toolbar(GtvMainToolbar* toolbar)
|
|
{
|
|
GtvMainToolbarPrivate& priv = getPrivate(toolbar);
|
|
return GTK_CONTAINER(priv->toolbar1);
|
|
}
|
|
|
|
GtkContainer*
|
|
gtv_main_toolbar_get_second_toolbar(GtvMainToolbar* toolbar)
|
|
{
|
|
GtvMainToolbarPrivate& priv = getPrivate(toolbar);
|
|
return GTK_CONTAINER(priv->toolbar2);
|
|
}
|
|
|
|
void
|
|
gtv_main_toolbar_set_sensitive_internal(GtvMainToolbar* toolbar, GtkToolItem* pItem, bool isSensitive)
|
|
{
|
|
GtvMainToolbarPrivate& priv = getPrivate(toolbar);
|
|
priv->m_aToolItemSensitivities[pItem] = isSensitive;
|
|
}
|
|
|
|
static void setSensitiveIfEdit(GtvMainToolbar* toolbar, GtkToolItem* pItem, bool bEdit)
|
|
{
|
|
GtvMainToolbarPrivate& priv = getPrivate(toolbar);
|
|
// some buttons remain enabled always
|
|
const gchar* pIconName = gtk_tool_button_get_icon_name(GTK_TOOL_BUTTON(pItem));
|
|
if (g_strcmp0(pIconName, "zoom-in-symbolic") != 0 &&
|
|
g_strcmp0(pIconName, "zoom-original-symbolic") != 0 &&
|
|
g_strcmp0(pIconName, "zoom-out-symbolic") != 0 &&
|
|
g_strcmp0(pIconName, "insert-text-symbolic") != 0 &&
|
|
g_strcmp0(pIconName, "view-continuous-symbolic") != 0 &&
|
|
g_strcmp0(pIconName, "document-properties") != 0 &&
|
|
g_strcmp0(pIconName, "system-run") != 0)
|
|
{
|
|
bool state = true;
|
|
if (priv->m_aToolItemSensitivities.find(pItem) != priv->m_aToolItemSensitivities.end())
|
|
state = priv->m_aToolItemSensitivities[pItem];
|
|
|
|
gtk_widget_set_sensitive(GTK_WIDGET(pItem), bEdit && state);
|
|
}
|
|
}
|
|
|
|
void
|
|
gtv_main_toolbar_set_edit(GtvMainToolbar* toolbar, gboolean bEdit)
|
|
{
|
|
GtvMainToolbarPrivate& priv = getPrivate(toolbar);
|
|
GtvGtkWrapper<GList> pList(gtk_container_get_children(GTK_CONTAINER(priv->toolbar1)),
|
|
[](GList* l)
|
|
{
|
|
g_list_free(l);
|
|
});
|
|
for (GList* l = pList.get(); l != nullptr; l = l->next)
|
|
{
|
|
if (GTK_IS_TOOL_BUTTON(l->data))
|
|
{
|
|
setSensitiveIfEdit(toolbar, GTK_TOOL_ITEM(l->data), bEdit);
|
|
}
|
|
}
|
|
|
|
pList.reset(gtk_container_get_children(GTK_CONTAINER(priv->toolbar2)));
|
|
for (GList* l = pList.get(); l != nullptr; l = l->next)
|
|
{
|
|
if (GTK_IS_TOOL_BUTTON(l->data))
|
|
{
|
|
setSensitiveIfEdit(toolbar, GTK_TOOL_ITEM(l->data), bEdit);
|
|
}
|
|
}
|
|
}
|
|
|
|
GtkWidget*
|
|
gtv_main_toolbar_new()
|
|
{
|
|
return GTK_WIDGET(g_object_new(GTV_TYPE_MAIN_TOOLBAR,
|
|
"orientation", GTK_ORIENTATION_VERTICAL,
|
|
nullptr));
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|