12 #include <sys/types.h>
15 #include <YCommandLine.h>
22 static std::string askForFileOrDirectory (GtkFileChooserAction action,
23 const std::string &path,
const std::string &filter,
const std::string &title);
25 static void errorMsg (
const char *msg)
27 GtkWidget* dialog = gtk_message_dialog_new (NULL,
28 GtkDialogFlags (0), GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
"%s", _(
"Error"));
29 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
"%s", msg);
30 gtk_dialog_run (GTK_DIALOG (dialog));
31 gtk_widget_destroy (dialog);
34 #define DEFAULT_MACRO_FILE_NAME "macro.ycp"
35 #define BUSY_CURSOR_TIMEOUT 250
37 YUI *createUI(
bool withThreads )
41 ui =
new YGUI (withThreads);
45 YGUI::YGUI (
bool with_threads)
46 : YUI (with_threads), m_done_init (false), busy_timeout (0)
48 yuiMilestone() <<
"This is libyui-gtk " << VERSION << std::endl;
50 m_no_border = m_fullscreen = m_swsingle =
false;
52 YGUI::setTextdomain( TEXTDOMAIN );
60 topmostConstructorHasFinished();
63 void YGUI::setTextdomain(
const char * domain )
65 bindtextdomain( domain, YSettings::localeDir().c_str() );
66 bind_textdomain_codeset( domain,
"utf8" );
71 extern int _nl_msg_cat_cntr;
76 static void print_log (
const gchar *domain, GLogLevelFlags level,
const gchar *message,
void *pData)
78 YUILogLevel_t ylevel = YUI_LOG_MILESTONE;
80 case G_LOG_LEVEL_ERROR:
81 case G_LOG_LEVEL_CRITICAL:
82 ylevel = YUI_LOG_ERROR;
84 case G_LOG_LEVEL_WARNING:
85 ylevel = YUI_LOG_WARNING;
87 case G_LOG_LEVEL_DEBUG:
88 ylevel = YUI_LOG_DEBUG;
90 case G_LOG_LEVEL_MESSAGE:
91 case G_LOG_LEVEL_INFO:
99 const char *component = domain ? g_intern_string (domain) :
"libyui-gtk";
100 YUILog::instance()->log (ylevel, component,
"libyui-gtk", 0,
"") << message << std::endl;
102 static int bugStop = 0;
108 void YGUI::checkInit()
115 YCommandLine cmdLine;
116 int argc = cmdLine.argc();
117 char **argv = cmdLine.argv();
118 for (
int i = 1; i < argc; i++) {
119 const char *argp = argv[i];
120 if (argp[0] !=
'-') {
121 if (!strcmp (argp,
"sw_single") || !strcmp (argp,
"online_update"))
126 if (argp[0] ==
'-') argp++;
128 if (!strcmp (argp,
"fullscreen"))
130 else if (!strcmp (argp,
"noborder"))
132 else if (!strcmp (argp,
"help")) {
134 _(
"Command line options for the YaST2 UI (GTK plugin):\n\n"
135 "--noborder no window manager border for main dialogs\n"
136 "--fullscreen use full screen for main dialogs\n"
137 "--nothreads run without additional UI threads\n"
138 "--help prints this help text\n"
145 gtk_init (&argc, &argv);
147 g_log_set_default_handler (print_log, NULL);
149 g_log_set_always_fatal (GLogLevelFlags (G_LOG_LEVEL_ERROR|G_LOG_LEVEL_CRITICAL|
150 G_LOG_LEVEL_WARNING| G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG));
152 std::string themeSubDir = YSettings::themeDir();
154 char* st = getenv(
"Y2STYLE");
155 std::string style = st ? st :
"";
159 style = themeSubDir + style;
163 style = themeSubDir +
"style.css";
166 yuiMilestone() <<
"Style \"" << style <<
"\"\n";
168 GtkCssProvider *provider = gtk_css_provider_new();
169 GFile * file = g_file_new_for_path(style.c_str());
170 if (g_file_query_exists(file, NULL))
172 GError *error = NULL;
173 if (!gtk_css_provider_load_from_file (provider, file, &error))
175 g_printerr (
"%s\n", error->message);
179 GdkDisplay *display = gdk_display_get_default ();
180 GdkScreen *screen = gdk_display_get_default_screen (display);
182 gtk_style_context_add_provider_for_screen (screen,
183 GTK_STYLE_PROVIDER (provider),
184 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
188 yuiMilestone() <<
"Style \"" << style <<
"\" not found. Ignoring style\n";
190 g_object_unref (provider);
192 GdkPixbuf *pixbuf = YGUtils::loadPixbuf (THEMEDIR
"/icons/32x32/apps/yast.png");
194 gtk_window_set_default_icon (pixbuf);
195 g_object_unref (G_OBJECT (pixbuf));
199 static gboolean ycp_wakeup_fn (GIOChannel *source, GIOCondition condition,
206 void YGUI::idleLoop (
int fd_ycp)
214 wakeup = g_io_channel_unix_new (fd_ycp);
215 g_io_channel_set_encoding (wakeup, NULL, NULL);
216 g_io_channel_set_buffered (wakeup, FALSE);
219 guint watch_tag = g_io_add_watch (wakeup, (GIOCondition)(G_IO_IN | G_IO_PRI),
220 ycp_wakeup_fn, &woken);
222 g_main_context_iteration (NULL, TRUE);
224 g_source_remove (watch_tag);
225 g_io_channel_unref (wakeup);
228 static gboolean user_input_timeout_cb (
YGUI *pThis)
230 if (!pThis->pendingEvent())
231 pThis->sendEvent (
new YTimeoutEvent());
236 YEvent *YGUI::waitInput (
unsigned long timeout_ms,
bool block)
239 if (!YDialog::currentDialog (
false))
249 timeout = g_timeout_add (timeout_ms,
250 (GSourceFunc) user_input_timeout_cb,
this);
253 while (!pendingEvent())
254 g_main_context_iteration (NULL, TRUE);
257 while (g_main_context_iteration (NULL, FALSE)) ;
259 YEvent *
event = NULL;
261 event = m_event_handler.consumePendingEvent();
265 g_source_remove (busy_timeout);
266 busy_timeout = g_timeout_add (BUSY_CURSOR_TIMEOUT, busy_timeout_cb,
this);
271 void YGUI::sendEvent (YEvent *event)
273 m_event_handler.sendEvent (event);
274 g_main_context_wakeup (NULL);
277 gboolean YGUI::busy_timeout_cb (gpointer data)
281 pThis->busy_timeout = 0;
285 void YGUI::busyCursor()
287 YGDialog *dialog = YGDialog::currentDialog();
289 dialog->busyCursor();
292 void YGUI::normalCursor()
295 g_source_remove (busy_timeout);
299 YGDialog *dialog = YGDialog::currentDialog();
301 dialog->normalCursor();
304 void YGUI::makeScreenShot()
307 YEvent *YGUI::runPkgSelection (YWidget *packageSelector)
309 yuiMilestone() <<
"Running package selection...\n";
313 event = packageSelector->findDialog()->waitForEvent();
314 }
catch (
const std::exception &e) {
315 yuiError() <<
"UI::RunPkgSelection() error: " << e.what() << std::endl;
316 yuiError() <<
"This is a libzypp problem. Do not file a bug against the UI!\n";
318 yuiError() <<
"UI::RunPkgSelection() error (unspecified)\n";
319 yuiError() <<
"This is a libzypp problem. Do not file a bug against the UI!\n";
324 void YGUI::askPlayMacro()
326 std::string filename = askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_OPEN,
327 DEFAULT_MACRO_FILE_NAME,
"*.ycp", _(
"Open Macro file"));
328 if (!filename.empty()) {
330 YMacro::play (filename);
331 sendEvent (
new YEvent());
335 void YGUI::toggleRecordMacro()
337 if (YMacro::recording()) {
338 YMacro::endRecording();
341 GtkWidget* dialog = gtk_message_dialog_new (NULL,
342 GtkDialogFlags (0), GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
"%s",
343 _(
"Macro recording done."));
344 gtk_dialog_run (GTK_DIALOG (dialog));
345 gtk_widget_destroy (dialog);
348 std::string filename = askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_SAVE,
349 DEFAULT_MACRO_FILE_NAME,
"*.ycp", _(
"Save Macro"));
350 if (!filename.empty())
351 YMacro::record (filename);
355 void YGUI::askSaveLogs()
357 std::string filename = askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_SAVE,
358 "/tmp/y2logs.tgz",
"*.tgz *.tar.gz", _(
"Save y2logs"));
359 if (!filename.empty()) {
360 std::string command =
"/usr/sbin/save_y2logs";
361 command +=
" '" + filename +
"'";
362 yuiMilestone() <<
"Saving y2logs: " << command << std::endl;
363 int ret = system (command.c_str());
365 yuiMilestone() <<
"y2logs saved to " << filename << std::endl;
367 char *error = g_strdup_printf (
368 _(
"Could not run: '%s' (exit value: %d)"),
369 command.c_str(), ret);
370 yuiError() << error << std::endl;
379 #define ICONDIR THEMEDIR "/icons/22x22/apps/"
381 YGApplication::YGApplication()
383 setIconBasePath (ICONDIR);
386 void YGApplication::makeScreenShot (
const std::string &_filename)
388 std::string filename (_filename);
389 bool interactive = filename.empty();
391 GtkWidget *widget = GTK_WIDGET (YGDialog::currentWindow());
394 errorMsg (_(
"No dialog to take screenshot of."));
399 gtk_widget_get_allocation(widget, &alloc);
403 gdk_pixbuf_get_from_window (gtk_widget_get_window(widget),
409 errorMsg (_(
"Could not take screenshot."));
416 if (screenShotNameTemplate.empty()) {
418 const char *homedir = getenv(
"HOME");
419 const char *ssdir = getenv(
"Y2SCREENSHOTS");
420 if (!homedir || !strcmp (homedir,
"/")) {
422 dir =
"/tmp/" + (ssdir ? (std::string(ssdir)) : (std::string(
"")));
423 if (mkdir (dir.c_str(), 0700) == -1)
427 dir = homedir + (ssdir ? (
"/" + std::string(ssdir)) : (std::string(
"")));
428 mkdir (dir.c_str(), 0750);
431 screenShotNameTemplate = dir +
"/%s-%03d.png";
435 const char *baseName =
"yast2-";
438 std::map <std::string, int>::iterator it = screenShotNb.find (baseName);
439 if (it == screenShotNb.end())
443 char *tmp_name = g_strdup_printf (screenShotNameTemplate.c_str(), baseName, nb);
447 yuiDebug() <<
"screenshot: " << filename << std::endl;
449 filename = askForFileOrDirectory (
450 GTK_FILE_CHOOSER_ACTION_SAVE,
"",
"*.png", _(
"Save screenshot"));
451 if (filename.empty()) {
452 yuiDebug() <<
"Save screen shot canceled by user\n";
453 goto makeScreenShot_ret;
456 screenShotNb.erase (baseName);
457 screenShotNb[baseName] = nb + 1;
460 yuiDebug() <<
"Saving screen shot to " << filename << std::endl;
461 if (!gdk_pixbuf_save (shot, filename.c_str(),
"png", &error, NULL)) {
462 std::string msg = _(
"Could not save to:");
463 msg +=
" "; msg += filename;
465 msg +=
"\n"; msg +=
"\n";
466 msg += error->message;
468 yuiError() << msg << std::endl;
470 errorMsg (msg.c_str());
471 goto makeScreenShot_ret;
475 g_object_unref (G_OBJECT (shot));
478 void YGApplication::beep()
480 GtkWindow *window = YGDialog::currentWindow();
482 gtk_window_present (window);
483 gtk_widget_error_bell (GTK_WIDGET (window));
492 std::string askForFileOrDirectory (GtkFileChooserAction action,
493 const std::string &path,
const std::string &filter,
const std::string &title)
495 GtkWindow *parent = YGDialog::currentWindow();
498 case GTK_FILE_CHOOSER_ACTION_SAVE:
499 button = _(
"_Save");
break;
500 case GTK_FILE_CHOOSER_ACTION_OPEN:
501 button = _(
"_Open");
break;
502 case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
503 case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
505 button = _(
"Select");
break;
508 dialog = gtk_file_chooser_dialog_new (title.c_str(),
509 parent, action, _(
"_Cancel"), GTK_RESPONSE_CANCEL,
510 button, GTK_RESPONSE_ACCEPT, NULL);
511 GtkFileChooser *fileChooser = GTK_FILE_CHOOSER (dialog);
512 gtk_file_chooser_set_local_only (fileChooser, TRUE);
513 gtk_file_chooser_set_do_overwrite_confirmation (fileChooser, TRUE);
516 std::string dirname, filename;
519 yuiWarning() <<
"FileDialog: Relative paths are not supported: '" << path <<
"'\n";
520 else if (!g_file_test (path.c_str(), G_FILE_TEST_EXISTS))
521 yuiWarning() <<
"FileDialog: Path doesn't exist: '" << path <<
"'\n";
522 else if (g_file_test (path.c_str(), G_FILE_TEST_IS_DIR))
525 std::string::size_type i = path.find_last_of (
"/");
526 if (i != std::string::npos) {
527 dirname = path.substr (0, i+1);
528 filename = path.substr (i+1);
533 if (!dirname.empty())
534 gtk_file_chooser_set_current_folder (fileChooser, dirname.c_str());
535 if (!filename.empty())
536 gtk_file_chooser_set_current_name (fileChooser, filename.c_str());
538 if (!filter.empty() && filter !=
"*") {
539 GtkFileFilter *gtk_filter = gtk_file_filter_new();
540 gtk_file_filter_set_name (gtk_filter, filter.c_str());
542 std::istringstream stream (filter);
543 while (!stream.eof()) {
546 if (!str.empty() && str [str.size()-1] ==
',')
547 str.erase (str.size()-1);
548 gtk_file_filter_add_pattern (gtk_filter, str.c_str());
550 gtk_file_chooser_add_filter (fileChooser, gtk_filter);
555 gtk_file_chooser_add_shortcut_folder (fileChooser,
"/", NULL);
558 if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) {
559 gchar *filename = gtk_file_chooser_get_filename (fileChooser);
565 gtk_widget_destroy (dialog);
569 std::string YGApplication::askForExistingDirectory (
570 const std::string &path,
const std::string &title)
571 {
return askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, path,
"", title); }
573 std::string YGApplication::askForExistingFile (
574 const std::string &path,
const std::string &filter,
const std::string &title)
575 {
return askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_OPEN, path, filter, title); }
577 std::string YGApplication::askForSaveFileName (
578 const std::string &path,
const std::string &filter,
const std::string &title)
579 {
return askForFileOrDirectory (GTK_FILE_CHOOSER_ACTION_SAVE, path, filter, title); }
581 std::string YGApplication::glyph (
const std::string &sym)
583 bool reverse = gtk_widget_get_default_direction() == GTK_TEXT_DIR_RTL;
584 if (sym == YUIGlyph_ArrowLeft)
585 return reverse ?
"\u25b6" :
"\u25c0";
586 if (sym == YUIGlyph_ArrowRight)
587 return reverse ?
"\u25c0" :
"\u25b6";
588 if (sym == YUIGlyph_ArrowUp)
590 if (sym == YUIGlyph_ArrowDown)
592 if (sym == YUIGlyph_CheckMark)
594 if (sym == YUIGlyph_BulletArrowRight)
595 return reverse ?
"\u21e6" :
"\u279c";
596 if (sym == YUIGlyph_BulletCircle)
598 if (sym == YUIGlyph_BulletSquare)
604 int YGApplication::deviceUnits (YUIDimension dim,
float size)
613 float YGApplication::layoutUnits (YUIDimension dim,
int units)
615 float size = (float) units;
616 if (dim == YD_HORIZ)
return size * (80/640.0);
617 else return size * (25/480.0);
620 static inline GdkScreen *getScreen ()
621 {
return gdk_display_get_default_screen (gdk_display_get_default()); }
624 int YGApplication::displayWidth()
626 GdkRectangle monitor;
627 gdk_monitor_get_geometry (
628 gdk_display_get_primary_monitor(gdk_display_get_default()),
630 return monitor.width;
634 int YGApplication::displayHeight()
636 GdkRectangle monitor;
637 gdk_monitor_get_geometry (
638 gdk_display_get_primary_monitor (gdk_display_get_default()),
640 return monitor.height;
643 int YGApplication::displayDepth()
645 # if GTK_CHECK_VERSION (3, 22, 0)
646 return gdk_visual_get_depth (gdk_screen_get_system_visual (
647 gdk_screen_get_default ()));
649 return gdk_visual_get_best_depth();
653 long YGApplication::displayColors()
654 {
return 1L << displayDepth(); }
657 int YGApplication::defaultWidth()
659 GdkRectangle availableSize = {0};
660 gdk_monitor_get_workarea(
661 gdk_display_get_primary_monitor(gdk_display_get_default()),
664 int width = availableSize.width;
665 if ( displayWidth() >= 1024 )
668 width = std::max( (
int) (availableSize.width * 0.7), 800 ) ;
674 int YGApplication::defaultHeight()
676 GdkRectangle availableSize = {0};
677 gdk_monitor_get_workarea(
678 gdk_display_get_primary_monitor(gdk_display_get_default()),
681 int height = availableSize.height;
682 if ( displayWidth() >= 1024 )
685 height = std::max( (
int) (availableSize.height * 0.7), 600 ) ;
691 YWidgetFactory *YGUI::createWidgetFactory()
693 YOptionalWidgetFactory *YGUI::createOptionalWidgetFactory()
695 YApplication *YGUI::createApplication()