1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 #include "gtv-application-window.hxx"
13 #include "gtv-main-toolbar.hxx"
14 #include "gtv-signal-handlers.hxx"
15 #include "gtv-helpers.hxx"
17 #include <LibreOfficeKit/LibreOfficeKitGtk.h>
25 struct GtvMainToolbarPrivateImpl
30 GtkWidget
* m_pEnableEditing
;
31 GtkWidget
* m_pLeftpara
;
32 GtkWidget
* m_pCenterpara
;
33 GtkWidget
* m_pRightpara
;
34 GtkWidget
* m_pJustifypara
;
35 GtkWidget
* m_pDeleteComment
;
36 GtkWidget
* m_pPartSelector
;
37 GtkWidget
* m_pPartModeSelector
;
38 GtkWidget
* m_pRecentUnoSelector
;
39 std::map
<std::string
, std::string
> m_pRecentUnoCommands
;
41 /// Sensitivity (enabled or disabled) for each tool item, ignoring edit state
42 std::map
<GtkToolItem
*, bool> m_aToolItemSensitivities
;
44 GtvMainToolbarPrivateImpl() :
47 m_pEnableEditing(nullptr),
49 m_pCenterpara(nullptr),
50 m_pRightpara(nullptr),
51 m_pJustifypara(nullptr),
52 m_pDeleteComment(nullptr),
53 m_pPartSelector(nullptr),
54 m_pPartModeSelector(nullptr),
55 m_pRecentUnoSelector(nullptr)
59 struct GtvMainToolbarPrivate
61 GtvMainToolbarPrivateImpl
* m_pImpl
;
63 GtvMainToolbarPrivateImpl
* operator->()
72 #if __has_warning("-Wdeprecated-volatile")
73 #pragma clang diagnostic push
74 #pragma clang diagnostic ignored "-Wdeprecated-volatile"
77 G_DEFINE_TYPE_WITH_PRIVATE(GtvMainToolbar
, gtv_main_toolbar
, GTK_TYPE_BOX
);
79 #if __has_warning("-Wdeprecated-volatile")
80 #pragma clang diagnostic pop
84 static GtvMainToolbarPrivate
&
85 getPrivate(GtvMainToolbar
* toolbar
)
87 return *static_cast<GtvMainToolbarPrivate
*>(gtv_main_toolbar_get_instance_private(toolbar
));
91 gtv_main_toolbar_init(GtvMainToolbar
* toolbar
)
93 GtvMainToolbarPrivate
& priv
= getPrivate(toolbar
);
94 priv
.m_pImpl
= new GtvMainToolbarPrivateImpl();
96 const std::string uiFilePath
= GtvHelpers::getDirPath(__FILE__
) + std::string(UI_FILE_NAME
);
97 GtvGtkWrapper
<GtkBuilder
> builder(gtk_builder_new_from_file(uiFilePath
.c_str()),
98 [](GtkBuilder
* pBuilder
) {
99 g_object_unref(pBuilder
);
102 priv
->toolbar1
= GTK_WIDGET(gtk_builder_get_object(builder
.get(), "toolbar1"));
103 gtk_box_pack_start(GTK_BOX(toolbar
), priv
->toolbar1
, false, false, false);
104 priv
->toolbar2
= GTK_WIDGET(gtk_builder_get_object(builder
.get(), "toolbar2"));
105 gtk_box_pack_start(GTK_BOX(toolbar
), priv
->toolbar2
, false, false, false);
107 priv
->m_pEnableEditing
= GTK_WIDGET(gtk_builder_get_object(builder
.get(), "btn_editmode"));
108 priv
->m_pLeftpara
= GTK_WIDGET(gtk_builder_get_object(builder
.get(), "btn_justifyleft"));
109 priv
->m_pCenterpara
= GTK_WIDGET(gtk_builder_get_object(builder
.get(), "btn_justifycenter"));
110 priv
->m_pRightpara
= GTK_WIDGET(gtk_builder_get_object(builder
.get(), "btn_justifyright"));
111 priv
->m_pJustifypara
= GTK_WIDGET(gtk_builder_get_object(builder
.get(), "btn_justifyfill"));
112 priv
->m_pDeleteComment
= GTK_WIDGET(gtk_builder_get_object(builder
.get(), "btn_removeannotation"));
113 priv
->m_pPartSelector
= GTK_WIDGET(gtk_builder_get_object(builder
.get(), "combo_partselector"));
114 priv
->m_pPartModeSelector
= GTK_WIDGET(gtk_builder_get_object(builder
.get(), "combo_partsmodeselector"));
115 priv
->m_pRecentUnoSelector
= GTK_WIDGET(gtk_builder_get_object(builder
.get(), "combo_recentunoselector"));
117 toolbar
->m_pAddressbar
= GTK_WIDGET(gtk_builder_get_object(builder
.get(), "addressbar_entry"));
118 toolbar
->m_pFormulabar
= GTK_WIDGET(gtk_builder_get_object(builder
.get(), "formulabar_entry"));
119 toolbar
->m_pContentControlSelector
120 = GTK_WIDGET(gtk_builder_get_object(builder
.get(), "combo_contentcontrolselector"));
121 toolbar
->m_pContentControlDateSelector
122 = GTK_WIDGET(gtk_builder_get_object(builder
.get(), "menu_contentcontroldateselector"));
124 // TODO: compile with -rdynamic and get rid of it
125 gtk_builder_add_callback_symbol(builder
.get(), "btn_clicked", G_CALLBACK(btn_clicked
));
126 gtk_builder_add_callback_symbol(builder
.get(), "doCopy", G_CALLBACK(doCopy
));
127 gtk_builder_add_callback_symbol(builder
.get(), "doPaste", G_CALLBACK(doPaste
));
128 gtk_builder_add_callback_symbol(builder
.get(), "createView", G_CALLBACK(createView
));
129 gtk_builder_add_callback_symbol(builder
.get(), "getRulerState", G_CALLBACK(getRulerState
));
130 gtk_builder_add_callback_symbol(builder
.get(), "recentUnoChanged", G_CALLBACK(recentUnoChanged
));
131 gtk_builder_add_callback_symbol(builder
.get(), "unoCommandDebugger", G_CALLBACK(unoCommandDebugger
));
132 gtk_builder_add_callback_symbol(builder
.get(), "commandValuesDebugger", G_CALLBACK(commandValuesDebugger
));
133 gtk_builder_add_callback_symbol(builder
.get(), "toggleEditing", G_CALLBACK(toggleEditing
));
134 gtk_builder_add_callback_symbol(builder
.get(), "changePartMode", G_CALLBACK(changePartMode
));
135 gtk_builder_add_callback_symbol(builder
.get(), "changePart", G_CALLBACK(changePart
));
136 gtk_builder_add_callback_symbol(builder
.get(), "changeContentControl",
137 G_CALLBACK(changeContentControl
));
138 gtk_builder_add_callback_symbol(builder
.get(), "changeDateContentControl",
139 G_CALLBACK(changeDateContentControl
));
140 gtk_builder_add_callback_symbol(builder
.get(), "changeZoom", G_CALLBACK(changeZoom
));
141 gtk_builder_add_callback_symbol(builder
.get(), "toggleFindbar", G_CALLBACK(toggleFindbar
));
142 gtk_builder_add_callback_symbol(builder
.get(), "documentRedline", G_CALLBACK(documentRedline
));
143 gtk_builder_add_callback_symbol(builder
.get(), "documentRepair", G_CALLBACK(documentRepair
));
144 gtk_builder_add_callback_symbol(builder
.get(), "signalAddressbar", G_CALLBACK(signalAddressbar
));
145 gtk_builder_add_callback_symbol(builder
.get(), "signalFormulabar", G_CALLBACK(signalFormulabar
));
148 // Note: These buttons are not the part of GtvMainToolbar
149 gtk_builder_add_callback_symbol(builder
.get(), "signalSearchNext", G_CALLBACK(signalSearchNext
));
150 gtk_builder_add_callback_symbol(builder
.get(), "signalSearchPrev", G_CALLBACK(signalSearchPrev
));
151 gtk_builder_add_callback_symbol(builder
.get(), "signalFindbar", G_CALLBACK(signalFindbar
));
152 gtk_builder_add_callback_symbol(builder
.get(), "toggleFindAll", G_CALLBACK(toggleFindAll
));
154 gtk_builder_connect_signals(builder
.get(), nullptr);
156 gtk_widget_show_all(GTK_WIDGET(toolbar
));
160 gtv_main_toolbar_finalize(GObject
* object
)
162 GtvMainToolbarPrivate
& priv
= getPrivate(GTV_MAIN_TOOLBAR(object
));
165 priv
.m_pImpl
= nullptr;
167 G_OBJECT_CLASS (gtv_main_toolbar_parent_class
)->finalize (object
);
171 gtv_main_toolbar_class_init(GtvMainToolbarClass
* klass
)
173 G_OBJECT_CLASS(klass
)->finalize
= gtv_main_toolbar_finalize
;
176 static void populatePartSelector(GtvMainToolbar
* toolbar
)
178 GtvMainToolbarPrivate
& priv
= getPrivate(toolbar
);
179 GtvApplicationWindow
* window
= GTV_APPLICATION_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(toolbar
)));
180 gtv_application_window_set_part_broadcast(window
, false);
181 gtk_list_store_clear( GTK_LIST_STORE(
182 gtk_combo_box_get_model(
183 GTK_COMBO_BOX(priv
->m_pPartSelector
) )) );
185 if (!window
->lokdocview
)
190 const int nMaxLength
= 50;
191 char sText
[nMaxLength
];
193 int nParts
= lok_doc_view_get_parts(LOK_DOC_VIEW(window
->lokdocview
));
194 for ( int i
= 0; i
< nParts
; i
++ )
196 char* pName
= lok_doc_view_get_part_name(LOK_DOC_VIEW(window
->lokdocview
), i
);
198 snprintf( sText
, nMaxLength
, "%i (%s)", i
+1, pName
);
201 gtk_combo_box_text_append_text( GTK_COMBO_BOX_TEXT(priv
->m_pPartSelector
), sText
);
203 gtk_combo_box_set_active(GTK_COMBO_BOX(priv
->m_pPartSelector
), lok_doc_view_get_part(LOK_DOC_VIEW(window
->lokdocview
)));
205 gtv_application_window_set_part_broadcast(window
, true);
208 static void populateRecentUnoSelector(GtvMainToolbar
* toolbar
)
210 GtvMainToolbarPrivate
& priv
= getPrivate(toolbar
);
211 GtkComboBoxText
* pSelector
= GTK_COMBO_BOX_TEXT(priv
->m_pRecentUnoSelector
);
213 unsigned counter
= 0;
214 std::ifstream
is("/tmp/gtv-recentunos.txt");
215 while (is
.good() && counter
< 10)
217 std::string unoCommandStr
;
218 std::getline(is
, unoCommandStr
);
219 std::vector
<std::string
> aUnoCmd
= GtvHelpers::split
<std::string
>(unoCommandStr
, " | ", 2);
220 if (aUnoCmd
.size() != 2)
222 auto it
= priv
->m_pRecentUnoCommands
.emplace(aUnoCmd
[0], aUnoCmd
[1]);
225 gtk_combo_box_text_append_text(pSelector
, aUnoCmd
[0].c_str());
232 gtv_main_toolbar_doc_loaded(GtvMainToolbar
* toolbar
, LibreOfficeKitDocumentType eDocType
, bool bEditMode
)
234 GtvMainToolbarPrivate
& priv
= getPrivate(toolbar
);
235 gtk_widget_set_visible(toolbar
->m_pAddressbar
, false);
236 gtk_widget_set_visible(toolbar
->m_pFormulabar
, false);
237 if (eDocType
== LOK_DOCTYPE_SPREADSHEET
)
239 gtk_tool_button_set_label(GTK_TOOL_BUTTON(priv
->m_pLeftpara
), ".uno:AlignLeft");
240 gtk_tool_button_set_label(GTK_TOOL_BUTTON(priv
->m_pCenterpara
), ".uno:AlignHorizontalCenter");
241 gtk_tool_button_set_label(GTK_TOOL_BUTTON(priv
->m_pRightpara
), ".uno:AlignRight");
242 gtk_widget_hide(priv
->m_pJustifypara
);
243 gtk_tool_button_set_label(GTK_TOOL_BUTTON(priv
->m_pDeleteComment
), ".uno:DeleteNote");
245 gtk_widget_set_visible(toolbar
->m_pAddressbar
, true);
246 gtk_widget_set_visible(toolbar
->m_pFormulabar
, true);
248 else if (eDocType
== LOK_DOCTYPE_PRESENTATION
)
250 gtk_tool_button_set_label(GTK_TOOL_BUTTON(priv
->m_pDeleteComment
), ".uno:DeleteAnnotation");
253 gtk_toggle_tool_button_set_active(GTK_TOGGLE_TOOL_BUTTON(priv
->m_pEnableEditing
), bEditMode
);
255 // populate combo boxes
256 populatePartSelector(toolbar
);
258 // populate recent uno selector
259 populateRecentUnoSelector(toolbar
);
263 gtv_main_toolbar_add_recent_uno(GtvMainToolbar
* toolbar
, const std::string
& rUnoCmdStr
)
265 GtvMainToolbarPrivate
& priv
= getPrivate(toolbar
);
266 GtkComboBoxText
* pSelector
= GTK_COMBO_BOX_TEXT(priv
->m_pRecentUnoSelector
);
268 const std::vector
<std::string
> aUnoCmd
= GtvHelpers::split
<std::string
>(rUnoCmdStr
, " | ", 2);
269 priv
->m_pRecentUnoCommands
[aUnoCmd
[0]] = aUnoCmd
[1];
270 // keep placeholder string at the top
271 gtk_combo_box_text_insert_text(pSelector
, 1, aUnoCmd
[0].c_str());
272 // TODO: Remove other text entries with same key
276 gtv_main_toolbar_get_recent_uno_args(GtvMainToolbar
* toolbar
, const std::string
& rUnoCmd
)
278 GtvMainToolbarPrivate
& priv
= getPrivate(toolbar
);
279 auto it
= std::find_if(priv
->m_pRecentUnoCommands
.begin(), priv
->m_pRecentUnoCommands
.end(),
280 [&rUnoCmd
](const std::pair
<std::string
, std::string
>& pair
) {
281 return rUnoCmd
== pair
.first
;
284 if (it
!= priv
->m_pRecentUnoCommands
.end())
290 gtv_main_toolbar_get_first_toolbar(GtvMainToolbar
* toolbar
)
292 GtvMainToolbarPrivate
& priv
= getPrivate(toolbar
);
293 return GTK_CONTAINER(priv
->toolbar1
);
297 gtv_main_toolbar_get_second_toolbar(GtvMainToolbar
* toolbar
)
299 GtvMainToolbarPrivate
& priv
= getPrivate(toolbar
);
300 return GTK_CONTAINER(priv
->toolbar2
);
304 gtv_main_toolbar_set_sensitive_internal(GtvMainToolbar
* toolbar
, GtkToolItem
* pItem
, bool isSensitive
)
306 GtvMainToolbarPrivate
& priv
= getPrivate(toolbar
);
307 priv
->m_aToolItemSensitivities
[pItem
] = isSensitive
;
310 static void setSensitiveIfEdit(GtvMainToolbar
* toolbar
, GtkToolItem
* pItem
, bool bEdit
)
312 GtvMainToolbarPrivate
& priv
= getPrivate(toolbar
);
313 // some buttons remain enabled always
314 const gchar
* pIconName
= gtk_tool_button_get_icon_name(GTK_TOOL_BUTTON(pItem
));
315 if (g_strcmp0(pIconName
, "zoom-in-symbolic") != 0 &&
316 g_strcmp0(pIconName
, "zoom-original-symbolic") != 0 &&
317 g_strcmp0(pIconName
, "zoom-out-symbolic") != 0 &&
318 g_strcmp0(pIconName
, "insert-text-symbolic") != 0 &&
319 g_strcmp0(pIconName
, "view-continuous-symbolic") != 0 &&
320 g_strcmp0(pIconName
, "document-properties") != 0 &&
321 g_strcmp0(pIconName
, "system-run") != 0)
324 if (priv
->m_aToolItemSensitivities
.find(pItem
) != priv
->m_aToolItemSensitivities
.end())
325 state
= priv
->m_aToolItemSensitivities
[pItem
];
327 gtk_widget_set_sensitive(GTK_WIDGET(pItem
), bEdit
&& state
);
332 gtv_main_toolbar_set_edit(GtvMainToolbar
* toolbar
, gboolean bEdit
)
334 GtvMainToolbarPrivate
& priv
= getPrivate(toolbar
);
335 GtvGtkWrapper
<GList
> pList(gtk_container_get_children(GTK_CONTAINER(priv
->toolbar1
)),
340 for (GList
* l
= pList
.get(); l
!= nullptr; l
= l
->next
)
342 if (GTK_IS_TOOL_BUTTON(l
->data
))
344 setSensitiveIfEdit(toolbar
, GTK_TOOL_ITEM(l
->data
), bEdit
);
348 pList
.reset(gtk_container_get_children(GTK_CONTAINER(priv
->toolbar2
)));
349 for (GList
* l
= pList
.get(); l
!= nullptr; l
= l
->next
)
351 if (GTK_IS_TOOL_BUTTON(l
->data
))
353 setSensitiveIfEdit(toolbar
, GTK_TOOL_ITEM(l
->data
), bEdit
);
359 gtv_main_toolbar_new()
361 return GTK_WIDGET(g_object_new(GTV_TYPE_MAIN_TOOLBAR
,
362 "orientation", GTK_ORIENTATION_VERTICAL
,
366 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */