Implemented gettext integration.

Marked all window texts for translation (library texts still to go).
Switched glade files to use gtk 3.20, added copyright information.
This commit is contained in:
Alexander Shaduri
2018-02-05 17:52:41 +00:00
parent 9e783a5afc
commit 5265ebb939
44 changed files with 2752 additions and 905 deletions
+1
View File
@@ -0,0 +1 @@
Makefile.in
+7
View File
@@ -0,0 +1,7 @@
svn propset svn:ignore -R -F .svnignore-default.txt .
for dir in . autoconf.m4 po; do
pushd $dir
svn propset svn:ignore -F .svnignore.txt .
popd
done
+3 -3
View File
@@ -1,4 +1,5 @@
0*
cmake-build-*
*.pcs
autom4te.cache
Makefile.in
@@ -6,13 +7,12 @@ configure
depcomp
config.guess
config.sub
config.rpath
aclocal.m4
config.h.in
compile
ar-lib
missing
install-sh
*.glade.cpp
*.ui.cpp
*.txt.cpp
.kdev4
.idea
-1
View File
@@ -1 +0,0 @@
svn propset svn:ignore -F .svnignore.txt .
File diff suppressed because it is too large Load Diff
+220
View File
@@ -0,0 +1,220 @@
# This cmake file is only for IDE integration, it should not be used
# to compile this program.
cmake_minimum_required(VERSION 3.5)
project(gsmartcontrol)
set(CMAKE_CXX_STANDARD 17)
find_package(PkgConfig)
pkg_check_modules(GTKMM gtkmm-3.0)
pkg_check_modules(PCRECPP libpcrecpp)
include_directories(SYSTEM
${GTKMM_INCLUDE_DIRS}
)
link_directories(${GTKMM_LIBRARY_DIRS})
# Clang5 doesn't understand libstdc++'s std::get(variant), so use libc++.
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
option(APP_COMPILER_CLANG_USE_LIBCXX "Use LLVM libc++ instead of gcc's libstdc++ (clang)" ON)
if (APP_COMPILER_CLANG_USE_LIBCXX)
add_compile_options(-stdlib=libc++)
endif()
endif()
set(_enable_clang_tidy OFF)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(_enable_clang_tidy ON)
endif()
option(APP_COMPILER_ANALYZE_CLANG_TIDY "Use clang-tidy in Analysis build type" ${_enable_clang_tidy})
set(APP_COMPILER_ANALYZE_CLANG_TIDY_CMDLINE "clang-tidy" # reads configuration from root-level .clang-tidy file
CACHE STRING "Command-line for clang-tidy.")
if (APP_COMPILER_ANALYZE_CLANG_TIDY)
set (CMAKE_CXX_CLANG_TIDY "${APP_COMPILER_ANALYZE_CLANG_TIDY_CMDLINE}")
endif()
add_compile_options(-Wall -Wextra -Wpedantic
-Wshadow -Wpointer-arith
-Wundef -Wunused-macros -Wcast-qual -Wcast-align -Wconversion
-Wmissing-declarations -Wpacked -Wredundant-decls -Wvla -Woverlength-strings
-Wnon-virtual-dtor -Woverloaded-virtual
-Wno-missing-field-initializers
)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
add_compile_options(
-Wdocumentation
-Wheader-guard
-Wloop-analysis
-Wno-keyword-macro
)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
add_compile_options(
-Wnoexcept
# -Wsuggest-attribute=const
-Wsuggest-attribute=noreturn
-Wsuggest-attribute=format
# -Wsuggest-final-types # works better with LTO
# -Wsuggest-final-methods
-Wsuggest-override
-Wno-virtual-move-assign
-Wdate-time
)
endif()
# Some warnings are only triggered at higher optimization levels
add_compile_options(-O2)
add_executable(gsmartcontrol
src/applib/app_builder_widget.h
src/applib/app_gtkmm_features.h
src/applib/app_gtkmm_utils.cpp
src/applib/app_gtkmm_utils.h
src/applib/app_pcrecpp.h
src/applib/cli_executors.h
src/applib/cmdex.cpp
src/applib/cmdex.h
src/applib/cmdex_sync.cpp
src/applib/cmdex_sync.h
src/applib/cmdex_sync_gui.cpp
src/applib/cmdex_sync_gui.h
src/applib/executor_factory.cpp
src/applib/executor_factory.h
src/applib/gui_utils.cpp
src/applib/gui_utils.h
src/applib/selftest.cpp
src/applib/selftest.h
src/applib/smartctl_executor.cpp
src/applib/smartctl_executor.h
src/applib/smartctl_executor_gui.h
# src/applib/smartctl_executor_example.cpp
src/applib/smartctl_parser.cpp
src/applib/smartctl_parser.h
# src/applib/smartctl_parser_example.cpp
# src/applib/spawn_example.cpp
src/applib/storage_detector.cpp
src/applib/storage_detector.h
src/applib/storage_detector_helpers.h
src/applib/storage_detector_linux.cpp
src/applib/storage_detector_linux.h
src/applib/storage_detector_other.cpp
src/applib/storage_detector_other.h
# src/applib/storage_detector_example.cpp
src/applib/storage_detector_win32.cpp
src/applib/storage_detector_win32.h
src/applib/storage_device.cpp
src/applib/storage_device.h
src/applib/storage_property.cpp
src/applib/storage_property.h
src/applib/storage_property_colors.h
src/applib/storage_property_descr.cpp
src/applib/storage_property_descr.h
src/applib/storage_settings.h
src/applib/warning_level.h
src/hz/bad_cast_exception.h
src/hz/data_file.h
src/hz/debug.h
src/hz/env_tools.h
src/hz/error.h
src/hz/error_holder.h
src/hz/format_unit.h
# src/hz/format_unit_example.cpp
src/hz/fs.h
src/hz/fs_ns.h
src/hz/instance_manager.h
src/hz/launch_url.h
src/hz/locale_tools.h
src/hz/process_signal.h
src/hz/scoped_ptr.h
src/hz/stream_cast.h
src/hz/string_algo.h
# src/hz/string_algo_example.cpp
src/hz/string_num.h
# src/hz/string_num_example.cpp
src/hz/string_sprintf.h
src/hz/system_specific.h
src/hz/win32_tools.h
src/libdebug/dchannel.cpp
src/libdebug/dchannel.h
src/libdebug/dcmdarg.cpp
src/libdebug/dcmdarg.h
src/libdebug/dexcept.h
src/libdebug/dflags.cpp
src/libdebug/dflags.h
src/libdebug/dout.cpp
src/libdebug/dout.h
src/libdebug/dstate.cpp
src/libdebug/dstate.h
src/libdebug/dstate_pub.h
src/libdebug/dstream.cpp
src/libdebug/dstream.h
src/libdebug/libdebug.h
src/libdebug/libdebug_mini.h
# src/libdebug/libdebug_example.cpp
src/rconfig/autosave.h
src/rconfig/loadsave.h
src/rconfig/config.h
# src/rconfig/rconfig_example.cpp
src/json/json.hpp
src/gsc_about_dialog.cpp
src/gsc_about_dialog.h
src/gsc_add_device_window.cpp
src/gsc_add_device_window.h
src/gsc_executor_error_dialog.cpp
src/gsc_executor_error_dialog.h
src/gsc_executor_log_window.cpp
src/gsc_executor_log_window.h
src/gsc_info_window.cpp
src/gsc_info_window.h
src/gsc_init.cpp
src/gsc_init.h
src/gsc_main.cpp
src/gsc_main_window.cpp
src/gsc_main_window.h
src/gsc_main_window_iconview.h
src/gsc_preferences_window.cpp
src/gsc_preferences_window.h
src/gsc_settings.h
src/gsc_text_window.h)
target_include_directories(gsmartcontrol
PRIVATE
src
${CMAKE_BINARY_DIR} # for config.h
)
target_compile_definitions(gsmartcontrol
PRIVATE
-DENABLE_GLIB=1
-DENABLE_GLIBMM=1
-D_GNU_SOURCE
-DPACKAGE_PKGDATA_DIR=\"/usr/local/share/gsmartcontrol\"
-DPACKAGE_SYSCONF_DIR=\"/usr/local/etc\"
-DPACKAGE_LOCALE_DIR=\"/usr/local/share/locale/gsmartcontrol\"
-DPACKAGE_DOC_DIR=\"/usr/share/doc/packages/gsmartcontrol\"
-DTOP_SOURCE_DIR="${CMAKE_SOURCE_DIR}"
-DHZ_USE_LIBDEBUG=1
-DHZ_ENABLE_COMPILED_RES_DATA
-DDEBUG_BUILD
)
target_link_libraries(gsmartcontrol
PRIVATE
${GTKMM_LDFLAGS}
${PCRECPP_LDFLAGS})
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
target_link_libraries(gsmartcontrol PRIVATE c++experimental)
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
target_link_libraries(gsmartcontrol PRIVATE stdc++fs)
endif()
+2 -2
View File
@@ -2,7 +2,7 @@
# Add autoconf.m4 directory to local macro search path
ACLOCAL_AMFLAGS = -I autoconf.m4
SUBDIRS = data debian.dist doc src
SUBDIRS = po data debian.dist doc src
# nobase_ preserves their directory names.
@@ -13,7 +13,7 @@ nobase_dist_doc_DATA = contrib/cron-based_noadmin/README \
# Extra files bundled with distribution.
EXTRA_DIST = COPYING ChangeLog Doxyfile INSTALL configure autogen.sh \
EXTRA_DIST = config.rpath COPYING ChangeLog Doxyfile INSTALL configure autogen.sh \
gsmartcontrol.kdev4 \
gsmartcontrol.spec
+8 -2
View File
@@ -41,6 +41,7 @@ JSON.
Port the rest to std::regex, get rid of pcre requirement.
Not sure, we still want to support old-format files.
Maybe make pcre optional (only for parsing the old format)
Add TESTS!
Use header-only formatting library:
For libdebug.
@@ -50,15 +51,20 @@ Use std::from_chars() in string_is_numeric_impl_classic_locale() (gcc 8)
Fix win32 crash.
Check if we need to distribute MIT license.
Detect and link with clang's / gcc's experimental lib, if needed.
Check TODOs
Mark with gettext
Make sure desktop file is translated.
Add french translation?
Win32: Bundle intl.dll and translations with windows distribution.
Add translations to .spec and .deb
Win32: Bundle gtk/glib/... translations for languages we support.
Before releasing 2.0.0:
Test with freebsd and macOS.
+32
View File
@@ -0,0 +1,32 @@
codeset.m4
extern-inline.m4
fcntl-o.m4
gettext.m4
glibc21.m4
glibc2.m4
iconv.m4
intdiv0.m4
intldir.m4
intl.m4
intlmacosx.m4
intmax.m4
inttypes_h.m4
inttypes-pri.m4
lcmessage.m4
lib-ld.m4
lib-link.m4
lib-prefix.m4
lock.m4
longlong.m4
nls.m4
po.m4
printf-posix.m4
progtest.m4
size_max.m4
stdint_h.m4
threadlib.m4
uintmax_t.m4
visibility.m4
wchar_t.m4
wint_t.m4
xsize.m4
+1 -3
View File
@@ -15,9 +15,7 @@
# echo "Running autoconf..."
# autoconf
autoreconf --verbose --install -W all --force
autoreconf --verbose --install --warnings=all --force
rm -f config.cache
+13 -8
View File
@@ -39,6 +39,15 @@ AC_PROG_LN_S
# -------------------------------------------------------------------------------------
# ------------- gettext support
AM_GNU_GETTEXT([external])
AM_GNU_GETTEXT_VERSION([0.19.2])
APP_LOCALEDIR=[${localedir}]
AC_SUBST(APP_LOCALEDIR)
# ------------- Detect compiler, OS, environment. Enable system features.
@@ -107,11 +116,6 @@ esac
CXXFLAGS="$CXXFLAGS -D_FILE_OFFSET_BITS=64"
# Arrange large file support (define _FILE_OFFSET_BITS 64, etc...).
# Adds the special flags to CC.
AC_SYS_LARGEFILE
# -------------------------------------------------------------------------------------
@@ -264,7 +268,8 @@ ADDITIONAL_FLAGS="-DPACKAGE_PKGDATA_DIR=\"\\\"\$(pkgdatadir)\\\"\" \
-DPACKAGE_SYSCONF_DIR=\"\\\"\$(sysconfdir)\\\"\" \
-DPACKAGE_DOC_DIR=\"\\\"\$(docdir)\\\"\" \
-DTOP_SOURCE_DIR=\"\\\"\$(top_srcdir)\\\"\" \
-DHZ_USE_LIBDEBUG=1
-DPACKAGE_LOCALE_DIR=\"\\\"\$(localedir)\\\"\" \
-DHZ_USE_LIBDEBUG=1"
CXXFLAGS="$CXXFLAGS $ADDITIONAL_FLAGS"
@@ -334,11 +339,11 @@ AC_CONFIG_FILES([data/gsmartcontrol-root], [chmod +x data/gsmartcontrol-root])
# these are all the makefiles to generate
AC_CONFIG_FILES([Makefile src/Makefile src/applib/Makefile src/res/Makefile src/hz/Makefile \
AC_CONFIG_FILES([Makefile src/Makefile src/applib/Makefile src/ui/Makefile src/hz/Makefile \
src/libdebug/Makefile src/rconfig/Makefile src/json/Makefile \
data/Makefile data/16/Makefile data/22/Makefile data/24/Makefile data/32/Makefile \
data/48/Makefile data/64/Makefile data/128/Makefile data/256/Makefile data/nsis/Makefile \
debian.dist/Makefile])
debian.dist/Makefile doc/Makefile po/Makefile.in])
AC_OUTPUT
+1 -1
View File
@@ -2,7 +2,7 @@
# These will be installed into docdir.
# Some of these files are actually needed at runtime.
dist_doc_DATA = AUTHORS.txt NEWS.txt README.txt \
dist_doc_DATA = AUTHORS.txt NEWS.txt README.txt TRANSLATORS.txt \
LICENSE_boost_1_0.txt \
LICENSE_gpl3.txt \
LICENSE_gsmartcontrol.txt \
View File
+11
View File
@@ -0,0 +1,11 @@
boldquot.sed
en@boldquot.header
en@quot.header
insert-header.sin
Makevars.template
quot.sed
remove-potcdate.sin
Rules-quot
Makefile.in
gsmartcontrol.pot
*.gmo
+2
View File
@@ -0,0 +1,2 @@
# keep this file sorted alphabetically, one language code per line
ka
+475
View File
@@ -0,0 +1,475 @@
# Makefile for PO directory in any package using GNU gettext.
# Copyright (C) 1995-1997, 2000-2007, 2009-2010 by Ulrich Drepper <drepper@gnu.ai.mit.edu>
#
# This file can be copied and used freely without restrictions. It can
# be used in projects which are not available under the GNU General Public
# License but which still want to provide support for the GNU gettext
# functionality.
# Please note that the actual code of GNU gettext is covered by the GNU
# General Public License and is *not* in the public domain.
#
# Origin: gettext-0.19
GETTEXT_MACRO_VERSION = 0.19
PACKAGE = @PACKAGE@
VERSION = @VERSION@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
SED = @SED@
SHELL = /bin/sh
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
prefix = @prefix@
exec_prefix = @exec_prefix@
datarootdir = @datarootdir@
datadir = @datadir@
localedir = @localedir@
gettextsrcdir = $(datadir)/gettext/po
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
# We use $(mkdir_p).
# In automake <= 1.9.x, $(mkdir_p) is defined either as "mkdir -p --" or as
# "$(mkinstalldirs)" or as "$(install_sh) -d". For these automake versions,
# @install_sh@ does not start with $(SHELL), so we add it.
# In automake >= 1.10, @mkdir_p@ is derived from ${MKDIR_P}, which is defined
# either as "/path/to/mkdir -p" or ".../install-sh -c -d". For these automake
# versions, $(mkinstalldirs) and $(install_sh) are unused.
mkinstalldirs = $(SHELL) @install_sh@ -d
install_sh = $(SHELL) @install_sh@
MKDIR_P = @MKDIR_P@
mkdir_p = @mkdir_p@
GMSGFMT_ = @GMSGFMT@
GMSGFMT_no = @GMSGFMT@
GMSGFMT_yes = @GMSGFMT_015@
GMSGFMT = $(GMSGFMT_$(USE_MSGCTXT))
MSGFMT_ = @MSGFMT@
MSGFMT_no = @MSGFMT@
MSGFMT_yes = @MSGFMT_015@
MSGFMT = $(MSGFMT_$(USE_MSGCTXT))
XGETTEXT_ = @XGETTEXT@
XGETTEXT_no = @XGETTEXT@
XGETTEXT_yes = @XGETTEXT_015@
XGETTEXT = $(XGETTEXT_$(USE_MSGCTXT))
MSGMERGE = msgmerge
MSGMERGE_UPDATE = @MSGMERGE@ --update
MSGINIT = msginit
MSGCONV = msgconv
MSGFILTER = msgfilter
POFILES = @POFILES@
GMOFILES = @GMOFILES@
UPDATEPOFILES = @UPDATEPOFILES@
DUMMYPOFILES = @DUMMYPOFILES@
DISTFILES.common = Makefile.in.in remove-potcdate.sin \
$(DISTFILES.common.extra1) $(DISTFILES.common.extra2) $(DISTFILES.common.extra3)
DISTFILES = $(DISTFILES.common) Makevars POTFILES.in \
$(POFILES) $(GMOFILES) \
$(DISTFILES.extra1) $(DISTFILES.extra2) $(DISTFILES.extra3)
POTFILES = \
CATALOGS = @CATALOGS@
POFILESDEPS_ = $(srcdir)/$(DOMAIN).pot
POFILESDEPS_yes = $(POFILESDEPS_)
POFILESDEPS_no =
POFILESDEPS = $(POFILESDEPS_$(PO_DEPENDS_ON_POT))
DISTFILESDEPS_ = update-po
DISTFILESDEPS_yes = $(DISTFILESDEPS_)
DISTFILESDEPS_no =
DISTFILESDEPS = $(DISTFILESDEPS_$(DIST_DEPENDS_ON_UPDATE_PO))
# Makevars gets inserted here. (Don't remove this line!)
.SUFFIXES:
.SUFFIXES: .po .gmo .mo .sed .sin .nop .po-create .po-update
.po.mo:
@echo "$(MSGFMT) -c -o $@ $<"; \
$(MSGFMT) -c -o t-$@ $< && mv t-$@ $@
.po.gmo:
@lang=`echo $* | sed -e 's,.*/,,'`; \
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
echo "$${cdcmd}rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o $${lang}.gmo $${lang}.po"; \
cd $(srcdir) && rm -f $${lang}.gmo && $(GMSGFMT) -c --statistics --verbose -o t-$${lang}.gmo $${lang}.po && mv t-$${lang}.gmo $${lang}.gmo
.sin.sed:
sed -e '/^#/d' $< > t-$@
mv t-$@ $@
all: all-@USE_NLS@
all-yes: stamp-po
all-no:
# Ensure that the gettext macros and this Makefile.in.in are in sync.
CHECK_MACRO_VERSION = \
test "$(GETTEXT_MACRO_VERSION)" = "@GETTEXT_MACRO_VERSION@" \
|| { echo "*** error: gettext infrastructure mismatch: using a Makefile.in.in from gettext version $(GETTEXT_MACRO_VERSION) but the autoconf macros are from gettext version @GETTEXT_MACRO_VERSION@" 1>&2; \
exit 1; \
}
# $(srcdir)/$(DOMAIN).pot is only created when needed. When xgettext finds no
# internationalized messages, no $(srcdir)/$(DOMAIN).pot is created (because
# we don't want to bother translators with empty POT files). We assume that
# LINGUAS is empty in this case, i.e. $(POFILES) and $(GMOFILES) are empty.
# In this case, stamp-po is a nop (i.e. a phony target).
# stamp-po is a timestamp denoting the last time at which the CATALOGS have
# been loosely updated. Its purpose is that when a developer or translator
# checks out the package via CVS, and the $(DOMAIN).pot file is not in CVS,
# "make" will update the $(DOMAIN).pot and the $(CATALOGS), but subsequent
# invocations of "make" will do nothing. This timestamp would not be necessary
# if updating the $(CATALOGS) would always touch them; however, the rule for
# $(POFILES) has been designed to not touch files that don't need to be
# changed.
stamp-po: $(srcdir)/$(DOMAIN).pot
@$(CHECK_MACRO_VERSION)
test ! -f $(srcdir)/$(DOMAIN).pot || \
test -z "$(GMOFILES)" || $(MAKE) $(GMOFILES)
@test ! -f $(srcdir)/$(DOMAIN).pot || { \
echo "touch stamp-po" && \
echo timestamp > stamp-poT && \
mv stamp-poT stamp-po; \
}
# Note: Target 'all' must not depend on target '$(DOMAIN).pot-update',
# otherwise packages like GCC can not be built if only parts of the source
# have been downloaded.
# This target rebuilds $(DOMAIN).pot; it is an expensive operation.
# Note that $(DOMAIN).pot is not touched if it doesn't need to be changed.
# The determination of whether the package xyz is a GNU one is based on the
# heuristic whether some file in the top level directory mentions "GNU xyz".
# If GNU 'find' is available, we avoid grepping through monster files.
$(DOMAIN).pot-update: $(POTFILES) $(srcdir)/POTFILES.in remove-potcdate.sed
package_gnu="$(PACKAGE_GNU)"; \
test -n "$$package_gnu" || { \
if { if (LC_ALL=C find --version) 2>/dev/null | grep GNU >/dev/null; then \
LC_ALL=C find -L $(top_srcdir) -maxdepth 1 -type f \
-size -10000000c -exec grep 'GNU @PACKAGE@' \
/dev/null '{}' ';' 2>/dev/null; \
else \
LC_ALL=C grep 'GNU @PACKAGE@' $(top_srcdir)/* 2>/dev/null; \
fi; \
} | grep -v 'libtool:' >/dev/null; then \
package_gnu=yes; \
else \
package_gnu=no; \
fi; \
}; \
if test "$$package_gnu" = "yes"; then \
package_prefix='GNU '; \
else \
package_prefix=''; \
fi; \
if test -n '$(MSGID_BUGS_ADDRESS)' || test '$(PACKAGE_BUGREPORT)' = '@'PACKAGE_BUGREPORT'@'; then \
msgid_bugs_address='$(MSGID_BUGS_ADDRESS)'; \
else \
msgid_bugs_address='$(PACKAGE_BUGREPORT)'; \
fi; \
case `$(XGETTEXT) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-5] | 0.1[0-5].* | 0.16 | 0.16.[0-1]*) \
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
--add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
--files-from=$(srcdir)/POTFILES.in \
--copyright-holder='$(COPYRIGHT_HOLDER)' \
--msgid-bugs-address="$$msgid_bugs_address" \
;; \
*) \
$(XGETTEXT) --default-domain=$(DOMAIN) --directory=$(top_srcdir) \
--add-comments=TRANSLATORS: $(XGETTEXT_OPTIONS) @XGETTEXT_EXTRA_OPTIONS@ \
--files-from=$(srcdir)/POTFILES.in \
--copyright-holder='$(COPYRIGHT_HOLDER)' \
--package-name="$${package_prefix}@PACKAGE@" \
--package-version='@VERSION@' \
--msgid-bugs-address="$$msgid_bugs_address" \
;; \
esac
test ! -f $(DOMAIN).po || { \
if test -f $(srcdir)/$(DOMAIN).pot; then \
sed -f remove-potcdate.sed < $(srcdir)/$(DOMAIN).pot > $(DOMAIN).1po && \
sed -f remove-potcdate.sed < $(DOMAIN).po > $(DOMAIN).2po && \
if cmp $(DOMAIN).1po $(DOMAIN).2po >/dev/null 2>&1; then \
rm -f $(DOMAIN).1po $(DOMAIN).2po $(DOMAIN).po; \
else \
rm -f $(DOMAIN).1po $(DOMAIN).2po $(srcdir)/$(DOMAIN).pot && \
mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \
fi; \
else \
mv $(DOMAIN).po $(srcdir)/$(DOMAIN).pot; \
fi; \
}
# This rule has no dependencies: we don't need to update $(DOMAIN).pot at
# every "make" invocation, only create it when it is missing.
# Only "make $(DOMAIN).pot-update" or "make dist" will force an update.
$(srcdir)/$(DOMAIN).pot:
$(MAKE) $(DOMAIN).pot-update
# This target rebuilds a PO file if $(DOMAIN).pot has changed.
# Note that a PO file is not touched if it doesn't need to be changed.
$(POFILES): $(POFILESDEPS)
@lang=`echo $@ | sed -e 's,.*/,,' -e 's/\.po$$//'`; \
if test -f "$(srcdir)/$${lang}.po"; then \
test -f $(srcdir)/$(DOMAIN).pot || $(MAKE) $(srcdir)/$(DOMAIN).pot; \
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
echo "$${cdcmd}$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot"; \
cd $(srcdir) \
&& { case `$(MSGMERGE_UPDATE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \
$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) $${lang}.po $(DOMAIN).pot;; \
*) \
$(MSGMERGE_UPDATE) $(MSGMERGE_OPTIONS) --lang=$${lang} $${lang}.po $(DOMAIN).pot;; \
esac; \
}; \
else \
$(MAKE) $${lang}.po-create; \
fi
install: install-exec install-data
install-exec:
install-data: install-data-@USE_NLS@
if test "$(PACKAGE)" = "gettext-tools"; then \
$(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
for file in $(DISTFILES.common) Makevars.template; do \
$(INSTALL_DATA) $(srcdir)/$$file \
$(DESTDIR)$(gettextsrcdir)/$$file; \
done; \
for file in Makevars; do \
rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
done; \
else \
: ; \
fi
install-data-no: all
install-data-yes: all
@catalogs='$(CATALOGS)'; \
for cat in $$catalogs; do \
cat=`basename $$cat`; \
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
dir=$(localedir)/$$lang/LC_MESSAGES; \
$(mkdir_p) $(DESTDIR)$$dir; \
if test -r $$cat; then realcat=$$cat; else realcat=$(srcdir)/$$cat; fi; \
$(INSTALL_DATA) $$realcat $(DESTDIR)$$dir/$(DOMAIN).mo; \
echo "installing $$realcat as $(DESTDIR)$$dir/$(DOMAIN).mo"; \
for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
if test -n "$$lc"; then \
if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
(cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
for file in *; do \
if test -f $$file; then \
ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
fi; \
done); \
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
else \
if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
:; \
else \
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
fi; \
fi; \
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
ln -s ../LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
ln $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo 2>/dev/null || \
cp -p $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(DOMAIN).mo $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
echo "installing $$realcat link as $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo"; \
fi; \
done; \
done
install-strip: install
installdirs: installdirs-exec installdirs-data
installdirs-exec:
installdirs-data: installdirs-data-@USE_NLS@
if test "$(PACKAGE)" = "gettext-tools"; then \
$(mkdir_p) $(DESTDIR)$(gettextsrcdir); \
else \
: ; \
fi
installdirs-data-no:
installdirs-data-yes:
@catalogs='$(CATALOGS)'; \
for cat in $$catalogs; do \
cat=`basename $$cat`; \
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
dir=$(localedir)/$$lang/LC_MESSAGES; \
$(mkdir_p) $(DESTDIR)$$dir; \
for lc in '' $(EXTRA_LOCALE_CATEGORIES); do \
if test -n "$$lc"; then \
if (cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc 2>/dev/null) | grep ' -> ' >/dev/null; then \
link=`cd $(DESTDIR)$(localedir)/$$lang && LC_ALL=C ls -l -d $$lc | sed -e 's/^.* -> //'`; \
mv $(DESTDIR)$(localedir)/$$lang/$$lc $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
(cd $(DESTDIR)$(localedir)/$$lang/$$lc.old && \
for file in *; do \
if test -f $$file; then \
ln -s ../$$link/$$file $(DESTDIR)$(localedir)/$$lang/$$lc/$$file; \
fi; \
done); \
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc.old; \
else \
if test -d $(DESTDIR)$(localedir)/$$lang/$$lc; then \
:; \
else \
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc; \
mkdir $(DESTDIR)$(localedir)/$$lang/$$lc; \
fi; \
fi; \
fi; \
done; \
done
# Define this as empty until I found a useful application.
installcheck:
uninstall: uninstall-exec uninstall-data
uninstall-exec:
uninstall-data: uninstall-data-@USE_NLS@
if test "$(PACKAGE)" = "gettext-tools"; then \
for file in $(DISTFILES.common) Makevars.template; do \
rm -f $(DESTDIR)$(gettextsrcdir)/$$file; \
done; \
else \
: ; \
fi
uninstall-data-no:
uninstall-data-yes:
catalogs='$(CATALOGS)'; \
for cat in $$catalogs; do \
cat=`basename $$cat`; \
lang=`echo $$cat | sed -e 's/\.gmo$$//'`; \
for lc in LC_MESSAGES $(EXTRA_LOCALE_CATEGORIES); do \
rm -f $(DESTDIR)$(localedir)/$$lang/$$lc/$(DOMAIN).mo; \
done; \
done
check: all
info dvi ps pdf html tags TAGS ctags CTAGS ID:
mostlyclean:
rm -f remove-potcdate.sed
rm -f stamp-poT
rm -f core core.* $(DOMAIN).po $(DOMAIN).1po $(DOMAIN).2po *.new.po
rm -fr *.o
clean: mostlyclean
distclean: clean
rm -f Makefile Makefile.in POTFILES *.mo
maintainer-clean: distclean
@echo "This command is intended for maintainers to use;"
@echo "it deletes files that may require special tools to rebuild."
rm -f stamp-po $(GMOFILES)
distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir)
dist distdir:
test -z "$(DISTFILESDEPS)" || $(MAKE) $(DISTFILESDEPS)
@$(MAKE) dist2
# This is a separate target because 'update-po' must be executed before.
dist2: stamp-po $(DISTFILES)
dists="$(DISTFILES)"; \
if test "$(PACKAGE)" = "gettext-tools"; then \
dists="$$dists Makevars.template"; \
fi; \
if test -f $(srcdir)/$(DOMAIN).pot; then \
dists="$$dists $(DOMAIN).pot stamp-po"; \
fi; \
if test -f $(srcdir)/ChangeLog; then \
dists="$$dists ChangeLog"; \
fi; \
for i in 0 1 2 3 4 5 6 7 8 9; do \
if test -f $(srcdir)/ChangeLog.$$i; then \
dists="$$dists ChangeLog.$$i"; \
fi; \
done; \
if test -f $(srcdir)/LINGUAS; then dists="$$dists LINGUAS"; fi; \
for file in $$dists; do \
if test -f $$file; then \
cp -p $$file $(distdir) || exit 1; \
else \
cp -p $(srcdir)/$$file $(distdir) || exit 1; \
fi; \
done
update-po: Makefile
$(MAKE) $(DOMAIN).pot-update
test -z "$(UPDATEPOFILES)" || $(MAKE) $(UPDATEPOFILES)
$(MAKE) update-gmo
# General rule for creating PO files.
.nop.po-create:
@lang=`echo $@ | sed -e 's/\.po-create$$//'`; \
echo "File $$lang.po does not exist. If you are a translator, you can create it through 'msginit'." 1>&2; \
exit 1
# General rule for updating PO files.
.nop.po-update:
@lang=`echo $@ | sed -e 's/\.po-update$$//'`; \
if test "$(PACKAGE)" = "gettext-tools"; then PATH=`pwd`/../src:$$PATH; fi; \
tmpdir=`pwd`; \
echo "$$lang:"; \
test "$(srcdir)" = . && cdcmd="" || cdcmd="cd $(srcdir) && "; \
echo "$${cdcmd}$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang $$lang.po $(DOMAIN).pot -o $$lang.new.po"; \
cd $(srcdir); \
if { case `$(MSGMERGE) --version | sed 1q | sed -e 's,^[^0-9]*,,'` in \
'' | 0.[0-9] | 0.[0-9].* | 0.1[0-7] | 0.1[0-7].*) \
$(MSGMERGE) $(MSGMERGE_OPTIONS) -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
*) \
$(MSGMERGE) $(MSGMERGE_OPTIONS) --lang=$$lang -o $$tmpdir/$$lang.new.po $$lang.po $(DOMAIN).pot;; \
esac; \
}; then \
if cmp $$lang.po $$tmpdir/$$lang.new.po >/dev/null 2>&1; then \
rm -f $$tmpdir/$$lang.new.po; \
else \
if mv -f $$tmpdir/$$lang.new.po $$lang.po; then \
:; \
else \
echo "msgmerge for $$lang.po failed: cannot move $$tmpdir/$$lang.new.po to $$lang.po" 1>&2; \
exit 1; \
fi; \
fi; \
else \
echo "msgmerge for $$lang.po failed!" 1>&2; \
rm -f $$tmpdir/$$lang.new.po; \
fi
$(DUMMYPOFILES):
update-gmo: Makefile $(GMOFILES)
@:
# Recreate Makefile by invoking config.status. Explicitly invoke the shell,
# because execution permission bits may not work on the current file system.
# Use @SHELL@, which is the shell determined by autoconf for the use by its
# scripts, not $(SHELL) which is hardwired to /bin/sh and may be deficient.
Makefile: Makefile.in.in Makevars $(top_builddir)/config.status @POMAKEFILEDEPS@
cd $(top_builddir) \
&& @SHELL@ ./config.status $(subdir)/$@.in po-directories
force:
# Tell versions [3.59,3.63) of GNU make not to export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
+72
View File
@@ -0,0 +1,72 @@
# Makefile variables for PO directory in any package using GNU gettext.
# Usually the message domain is the same as the package name.
DOMAIN = gsmartcontrol
# These two variables depend on the location of this directory.
subdir = po
top_builddir = ..
# These options get passed to xgettext.
XGETTEXT_OPTIONS = --keyword=_ --keyword=N_
# This is the copyright holder that gets inserted into the header of the
# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding
# package. (Note that the msgstr strings, extracted from the package's
# sources, belong to the copyright holder of the package.) Translators are
# expected to transfer the copyright for their translations to this person
# or entity, or to disclaim their copyright. The empty string stands for
# the public domain; in this case the translators are expected to disclaim
# their copyright.
COPYRIGHT_HOLDER = Alexander Shaduri
# This tells whether or not to prepend "GNU " prefix to the package
# name that gets inserted into the header of the $(DOMAIN).pot file.
# Possible values are "yes", "no", or empty. If it is empty, try to
# detect it automatically by scanning the files in $(top_srcdir) for
# "GNU packagename" string.
PACKAGE_GNU = no
# This is the email address or URL to which the translators shall report
# bugs in the untranslated strings:
# - Strings which are not entire sentences, see the maintainer guidelines
# in the GNU gettext documentation, section 'Preparing Strings'.
# - Strings which use unclear terms or require additional context to be
# understood.
# - Strings which make invalid assumptions about notation of date, time or
# money.
# - Pluralisation problems.
# - Incorrect English spelling.
# - Incorrect formatting.
# It can be your email address, or a mailing list address where translators
# can write to without being subscribed, or the URL of a web page through
# which the translators can contact you.
MSGID_BUGS_ADDRESS = https://gsmartcontrol.sourceforge.io/home/index.php/Support
# This is the list of locale categories, beyond LC_MESSAGES, for which the
# message catalogs shall be used. It is usually empty.
EXTRA_LOCALE_CATEGORIES =
# This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt'
# context. Possible values are "yes" and "no". Set this to yes if the
# package uses functions taking also a message context, like pgettext(), or
# if in $(XGETTEXT_OPTIONS) you define keywords with a context argument.
USE_MSGCTXT = no
# These options get passed to msgmerge.
# Useful options are in particular:
# --previous to keep previous msgids of translated messages,
# --quiet to reduce the verbosity.
MSGMERGE_OPTIONS =
# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
# has changed. Possible values are "yes" and "no". Set this to no if
# the POT file is checked in the repository and the version control
# program ignores timestamps.
PO_DEPENDS_ON_POT = yes
# This tells whether or not to forcibly update $(DOMAIN).pot and
# regenerate PO files on "make dist". Possible values are "yes" and
# "no". Set this to no if the POT file and PO files are maintained
# externally.
DIST_DEPENDS_ON_UPDATE_PO = yes
+20
View File
@@ -0,0 +1,20 @@
src/ui/gsc_about_dialog.glade
src/ui/gsc_add_device_window.glade
src/ui/gsc_executor_log_window.glade
src/ui/gsc_info_window.glade
src/ui/gsc_main_window.glade
src/ui/gsc_preferences_window.glade
src/ui/gsc_text_window.glade
src/add_device_window.cpp
src/gsc_main_window.cpp
src/gsc_executor_error_dialog.cpp
src/gsc_executor_log_window.cpp
src/gsc_info_window.cpp
src/gsc_init.cpp
src/gsc_main_window.cpp
src/gsc_main_window_iconview.h
src/gsc_preferences_window.cpp
src/gsc_text_window.h
hz/format_unit.h
+30
View File
@@ -0,0 +1,30 @@
# Georgian translations for gsmartcontrol package.
# Copyright (C) 2018 Alexander Shaduri
# This file is distributed under the same license as the gsmartcontrol package.
# Alexander Shaduri <ashaduri@gmail.com>, 2018.
#
msgid ""
msgstr ""
"Project-Id-Version: gsmartcontrol 2.0.0\n"
"Report-Msgid-Bugs-To: https://gsmartcontrol.sourceforge.io/home/index.php/"
"Support\n"
"POT-Creation-Date: 2018-02-05 01:51+0400\n"
"PO-Revision-Date: 2018-02-05 01:22+0400\n"
"Last-Translator: Alexander Shaduri <ashaduri@gmail.com>\n"
"Language-Team: Georgian\n"
"Language: ka\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/ui/gsc_main_window.glade:70
msgid "Drive information:"
msgstr "ინფორმაცია დრაივის შესახებ:"
#: src/ui/gsc_main_window.glade:85
msgid "Basic health check:"
msgstr "ზოგადი ჯანმრთელობა:"
#: src/ui/gsc_main_window.glade:100
msgid "Model family:"
msgstr "მოდელების ოჯახი:"
+2 -2
View File
@@ -36,7 +36,7 @@ void app_gtkmm_set_widget_tooltip(Gtk::Widget& widget,
/// Convenience function for creating a TreeViewColumn .
template<typename T>
int app_gtkmm_create_tree_view_column(Gtk::TreeModelColumn<T>& mcol, Gtk::TreeView& treeview,
const Glib::ustring& title, const Glib::ustring& tooltip_text, bool sortable = false, bool cell_markup = false)
const Glib::ustring& title, const Glib::ustring& tooltip_text, bool sortable = false, bool cell_markup = false, bool tooltip_markup = false)
{
int num_tree_cols = treeview.append_column(title, mcol);
Gtk::TreeViewColumn* tcol = treeview.get_column(num_tree_cols - 1);
@@ -50,7 +50,7 @@ int app_gtkmm_create_tree_view_column(Gtk::TreeModelColumn<T>& mcol, Gtk::TreeVi
Gtk::Widget* header = app_gtkmm_get_column_header(*tcol);
if (header)
app_gtkmm_set_widget_tooltip(*header, tooltip_text);
app_gtkmm_set_widget_tooltip(*header, tooltip_text, tooltip_markup);
}
if (cell_markup) {
+5 -2
View File
@@ -16,6 +16,8 @@
#include <string>
#include <chrono>
#include <utility>
#include <glibmm/i18n.h>
#include "hz/error.h"
#include "hz/process_signal.h" // hz::SIGNAL_*
@@ -66,7 +68,8 @@ class CmdexSync : public sigc::trackable {
/// Constructor
CmdexSync()
{
running_msg_ = "Running %s..."; // %s will be replaced by command basename
/// Translators: {command} will be replaced by command name.
running_msg_ = _("Running {command}...");
set_error_header("An error occurred while executing the command:\n\n");
}
@@ -189,7 +192,7 @@ class CmdexSync : public sigc::trackable {
}
/// Set a message to display when running. %s in \c msg will be replaced by the command.
/// Set a message to display when running. "{command}" in \c msg will be replaced by the command.
void set_running_msg(const std::string& msg)
{
running_msg_ = msg;
+3 -3
View File
@@ -15,7 +15,7 @@
#include <gtkmm.h> // Gtk::Main
#include <gdkmm.h>
#include "hz/string_sprintf.h"
#include "hz/string_algo.h"
#include "hz/fs_ns.h"
#include "cmdex_sync_gui.h"
@@ -133,8 +133,8 @@ void CmdexSyncGui::set_running_dialog_abort_mode(bool aborting)
} else if (!aborting) {
std::string msg = hz::string_sprintf(get_running_msg().c_str(),
hz::fs::u8path(this->get_command_name()).filename().u8string().c_str());
std::string msg = hz::string_replace_copy(get_running_msg(), "{command}",
hz::fs::u8path(this->get_command_name()).filename().u8string());
running_dialog_->set_message("\n " + msg + " ");
// running_dialog_->set_response_sensitive(Gtk::RESPONSE_CANCEL, true);
+6 -5
View File
@@ -36,13 +36,11 @@ GscAboutDialog::GscAboutDialog(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk::Builde
// set these properties here (after setting hooks) to make the links work.
set_website("https://gsmartcontrol.sourceforge.io/");
set_license(hz::data_file_get_contents("doc", "LICENSE_gsmartcontrol.txt", 1*1024*1024)); // 1M
// This overrides set_license(), so don't do it.
// set_license_type(Gtk::LICENSE_GPL_3_0_ONLY);
// set_license_type(Gtk::LICENSE_GPL_3_0_ONLY); // this overrides set_license()
// set_license(hz::data_file_get_contents("doc", "LICENSE_gsmartcontrol.txt", 1*1024*1024)); // 1M
// spammers go away
set_copyright("Copyright (C) 2008 - 2018 Alexander Shaduri " "<ashaduri" "" "@" "" "" "gmail.com>");
set_copyright(Glib::ustring::compose("Copyright (C) %1", "2008 - 2018 Alexander Shaduri " "<ashaduri" "" "@" "" "" "gmail.com>"));
std::string authors_str = hz::data_file_get_contents("doc", "AUTHORS.txt", 1*1024*1024); // 1M
hz::string_any_to_unix(authors_str);
@@ -60,6 +58,9 @@ GscAboutDialog::GscAboutDialog(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk::Builde
set_documenters(authors);
std::string translators_str = hz::data_file_get_contents("doc", "TRANSLATORS.txt", 10*1024*1024); // 10M
set_translator_credits(translators_str);
// run(); // don't use run - it's difficult to exit it manually.
// show(); // shown by the caller to enable setting the parent window.
}
+12 -7
View File
@@ -13,6 +13,7 @@
#include "local_glibmm.h"
#include <gtkmm.h>
#include <glibmm/i18n.h>
#include <gdk/gdk.h> // GDK_KEY_Escape
#include "hz/fs_ns.h"
@@ -41,11 +42,15 @@ GscAddDeviceWindow::GscAddDeviceWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk
APP_BUILDER_AUTO_CONNECT(device_name_browse_button, clicked);
Glib::ustring device_name_tooltip = "Device name";
auto top_info_link_label = lookup_widget<Gtk::Label*>("top_info_link_label");
std::string man_url = "https://gsmartcontrol.sourceforge.io/smartctl_man.html";
top_info_link_label->set_text(Glib::ustring::compose(top_info_link_label->get_text(), man_url));
Glib::ustring device_name_tooltip = _("Device name");
#if defined CONFIG_KERNEL_FAMILY_WINDOWS
device_name_tooltip = "Device name (for example, use \"pd0\" for the first physical drive)";
device_name_tooltip = _("Device name (for example, use \"pd0\" for the first physical drive)");
#elif defined CONFIG_KERNEL_LINUX
device_name_tooltip = "Device name (for example, /dev/sda or /dev/twa0)";
device_name_tooltip = _("Device name (for example, /dev/sda or /dev/twa0)");
#endif
if (auto* device_name_label = lookup_widget<Gtk::Label*>("device_name_label")) {
app_gtkmm_set_widget_tooltip(*device_name_label, device_name_tooltip);
@@ -58,9 +63,9 @@ GscAddDeviceWindow::GscAddDeviceWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk
}
Glib::ustring device_type_tooltip = "Smartctl -d option parameter";
Glib::ustring device_type_tooltip = _("Smartctl -d option parameter");
#if defined CONFIG_KERNEL_LINUX || defined CONFIG_KERNEL_FAMILY_WINDOWS
device_type_tooltip = "Smartctl -d option parameter. For example, use areca,1 for the first drive behind Areca RAID controller.";
device_type_tooltip = _("Smartctl -d option parameter. For example, use areca,1 for the first drive behind Areca RAID controller.");
#endif
if (auto* device_type_label = lookup_widget<Gtk::Label*>("device_type_label")) {
app_gtkmm_set_widget_tooltip(*device_type_label, device_type_tooltip);
@@ -176,7 +181,7 @@ void GscAddDeviceWindow::on_device_name_browse_button_clicked()
#if GTK_CHECK_VERSION(3, 20, 0)
hz::scoped_ptr<GtkFileChooserNative> dialog(gtk_file_chooser_native_new(
"Choose Device...", this->gobj(), GTK_FILE_CHOOSER_ACTION_OPEN, nullptr, nullptr), g_object_unref);
_("Choose Device..."), this->gobj(), GTK_FILE_CHOOSER_ACTION_OPEN, nullptr, nullptr), g_object_unref);
if (path.is_absolute())
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog.get()), path.u8string().c_str());
@@ -184,7 +189,7 @@ void GscAddDeviceWindow::on_device_name_browse_button_clicked()
result = gtk_native_dialog_run(GTK_NATIVE_DIALOG(dialog.get()));
#else
Gtk::FileChooserDialog dialog(*this, "Choose Device...",
Gtk::FileChooserDialog dialog(*this, _("Choose Device..."),
Gtk::FILE_CHOOSER_ACTION_OPEN);
// Add response buttons the the dialog
@@ -13,6 +13,7 @@
#include "local_glibmm.h"
#include <gtkmm.h>
#include <glibmm/i18n.h>
#include "gsc_executor_log_window.h"
#include "gsc_executor_error_dialog.h"
@@ -49,7 +50,7 @@ namespace {
dialog.add_action_widget(ok_button, Gtk::RESPONSE_OK);
Gtk::Button output_button("_Show Output", true); // don't put this inside if, it needs to live beyond it.
Gtk::Button output_button(_("_Show Output"), true); // don't put this inside if, it needs to live beyond it.
if (show_output_button) {
output_button.show_all();
dialog.add_action_widget(output_button, Gtk::RESPONSE_HELP);
+13 -12
View File
@@ -15,6 +15,7 @@
#include <sstream>
#include <cstddef> // std::size_t
#include <gtkmm.h>
#include <glibmm/i18n.h>
#include <gdk/gdk.h> // GDK_KEY_Escape
#include "applib/app_gtkmm_utils.h" // app_gtkmm_create_tree_view_column
@@ -68,11 +69,11 @@ GscExecutorLogWindow::GscExecutorLogWindow(BaseObjectType* gtkcobj, Glib::RefPtr
model_columns.add(col_num);
app_gtkmm_create_tree_view_column(col_num, *treeview,
"#", "# of executed command", true); // sortable
"#", _("# of executed command"), true); // sortable
model_columns.add(col_command);
app_gtkmm_create_tree_view_column(col_command, *treeview,
"Command", "Command with parameters", true); // sortable
_("Command"), _("Command with parameters"), true); // sortable
model_columns.add(col_entry);
@@ -200,16 +201,16 @@ void GscExecutorLogWindow::on_window_save_current_button_clicked()
int result = 0;
Glib::RefPtr<Gtk::FileFilter> specific_filter = Gtk::FileFilter::create();
specific_filter->set_name("Text Files");
specific_filter->set_name(_("Text Files"));
specific_filter->add_pattern("*.txt");
Glib::RefPtr<Gtk::FileFilter> all_filter = Gtk::FileFilter::create();
all_filter->set_name("All Files");
all_filter->set_name(_("All Files"));
all_filter->add_pattern("*");
#if GTK_CHECK_VERSION(3, 20, 0)
hz::scoped_ptr<GtkFileChooserNative> dialog(gtk_file_chooser_native_new(
"Save Data As...", this->gobj(), GTK_FILE_CHOOSER_ACTION_SAVE, nullptr, nullptr), g_object_unref);
_("Save Data As..."), this->gobj(), GTK_FILE_CHOOSER_ACTION_SAVE, nullptr, nullptr), g_object_unref);
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog.get()), true);
@@ -224,7 +225,7 @@ void GscExecutorLogWindow::on_window_save_current_button_clicked()
result = gtk_native_dialog_run(GTK_NATIVE_DIALOG(dialog.get()));
#else
Gtk::FileChooserDialog dialog(*this, "Save Data As...",
Gtk::FileChooserDialog dialog(*this, _("Save Data As..."),
Gtk::FILE_CHOOSER_ACTION_SAVE);
// Add response buttons the the dialog
@@ -265,7 +266,7 @@ void GscExecutorLogWindow::on_window_save_current_button_clicked()
auto ec = hz::fs_file_put_contents(hz::fs::u8path(file), entry->std_output);
if (ec) {
gui_show_error_dialog("Cannot save data to file", ec.message(), this);
gui_show_error_dialog(_("Cannot save data to file"), ec.message(), this);
}
break;
}
@@ -317,16 +318,16 @@ void GscExecutorLogWindow::on_window_save_all_button_clicked()
int result = 0;
Glib::RefPtr<Gtk::FileFilter> specific_filter = Gtk::FileFilter::create();
specific_filter->set_name("Text Files");
specific_filter->set_name(_("Text Files"));
specific_filter->add_pattern("*.txt");
Glib::RefPtr<Gtk::FileFilter> all_filter = Gtk::FileFilter::create();
all_filter->set_name("All Files");
all_filter->set_name(_("All Files"));
all_filter->add_pattern("*");
#if GTK_CHECK_VERSION(3, 20, 0)
hz::scoped_ptr<GtkFileChooserNative> dialog(gtk_file_chooser_native_new(
"Save Data As...", this->gobj(), GTK_FILE_CHOOSER_ACTION_SAVE, nullptr, nullptr), g_object_unref);
_("Save Data As..."), this->gobj(), GTK_FILE_CHOOSER_ACTION_SAVE, nullptr, nullptr), g_object_unref);
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog.get()), true);
@@ -341,7 +342,7 @@ void GscExecutorLogWindow::on_window_save_all_button_clicked()
result = gtk_native_dialog_run(GTK_NATIVE_DIALOG(dialog.get()));
#else
Gtk::FileChooserDialog dialog(*this, "Save Data As...",
Gtk::FileChooserDialog dialog(*this, _("Save Data As..."),
Gtk::FILE_CHOOSER_ACTION_SAVE);
// Add response buttons the the dialog
@@ -382,7 +383,7 @@ void GscExecutorLogWindow::on_window_save_all_button_clicked()
auto ec = hz::fs_file_put_contents(hz::fs::u8path(file), exss.str());
if (ec) {
gui_show_error_dialog("Cannot save data to file", ec.message(), this);
gui_show_error_dialog(_("Cannot save data to file"), ec.message(), this);
}
break;
}
+119 -110
View File
@@ -13,6 +13,7 @@
#include "local_glibmm.h"
#include <gtkmm.h>
#include <glibmm/i18n.h>
#include <gdk/gdk.h> // GDK_KEY_Escape
#include <vector> // better use vector, it's needed by others too
#include <algorithm> // std::min, std::max
@@ -36,6 +37,11 @@
#include "gsc_startup_settings.h"
using namespace std::literals;
/// A label for StorageProperty
struct PropertyLabel {
/// Constructor
@@ -193,7 +199,7 @@ GscInfoWindow::GscInfoWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk::Builder>
// Create missing widgets
auto* device_name_hbox = lookup_widget<Gtk::Box*>("device_name_label_hbox");
if (device_name_hbox) {
device_name_label = Gtk::manage(new Gtk::Label("No data available", Gtk::ALIGN_START));
device_name_label = Gtk::manage(new Gtk::Label(_("No data available"), Gtk::ALIGN_START));
device_name_label->set_selectable(true);
device_name_label->show();
device_name_hbox->pack_start(*device_name_label, true, true);
@@ -245,7 +251,7 @@ GscInfoWindow::GscInfoWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk::Builder>
treeview->signal_button_press_event().connect(
sigc::bind(sigc::bind(sigc::mem_fun(*this, &GscInfoWindow::on_treeview_button_press_event), treeview), treeview_menus[treeview_name]), false); // before
Gtk::MenuItem* item = Gtk::manage(new Gtk::MenuItem("Copy Selected Data", true));
Gtk::MenuItem* item = Gtk::manage(new Gtk::MenuItem(_("Copy Selected Data"), true));
item->signal_activate().connect(
sigc::bind(sigc::mem_fun(*this, &GscInfoWindow::on_treeview_menu_copy_clicked), treeview) );
treeview_menus[treeview_name]->append(*item);
@@ -262,27 +268,27 @@ GscInfoWindow::GscInfoWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk::Builder>
// on them in gtkbuilder.
if (auto* textview = lookup_widget<Gtk::TextView*>("error_log_textview")) {
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
buffer->set_text("\nNo data available");
buffer->set_text("\n"s + _("No data available"));
}
if (auto* textview = lookup_widget<Gtk::TextView*>("selective_selftest_log_textview")) {
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
buffer->set_text("\nNo data available");
buffer->set_text("\n"s + _("No data available"));
}
if (auto* textview = lookup_widget<Gtk::TextView*>("temperature_log_textview")) {
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
buffer->set_text("\nNo data available");
buffer->set_text("\n"s + _("No data available"));
}
if (auto* textview = lookup_widget<Gtk::TextView*>("erc_log_textview")) {
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
buffer->set_text("\nNo data available");
buffer->set_text("\n"s + _("No data available"));
}
if (auto* textview = lookup_widget<Gtk::TextView*>("phy_log_textview")) {
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
buffer->set_text("\nNo data available");
buffer->set_text("\n"s + _("No data available"));
}
if (auto* textview = lookup_widget<Gtk::TextView*>("directory_log_textview")) {
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
buffer->set_text("\nNo data available");
buffer->set_text("\n"s + _("No data available"));
}
@@ -369,11 +375,11 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
// fetch all smartctl info, even if it already has it (to refresh it).
if (scan) {
std::shared_ptr<SmartctlExecutorGui> ex(new SmartctlExecutorGui());
ex->create_running_dialog(this, "Running %s on " + drive->get_device_with_type() + "...");
ex->create_running_dialog(this, Glib::ustring::compose(_("Running {command} on %1..."), drive->get_device_with_type()));
std::string error_msg = drive->fetch_data_and_parse(ex); // run it with GUI support
if (!error_msg.empty()) {
gsc_executor_error_dialog_show("Cannot retrieve SMART data", error_msg, this);
gsc_executor_error_dialog_show(_("Cannot retrieve SMART data"), error_msg, this);
return;
}
}
@@ -384,7 +390,7 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
auto* b = lookup_widget<Gtk::Button*>("refresh_info_button");
if (b) {
b->set_sensitive(false);
app_gtkmm_set_widget_tooltip(*b, "Cannot re-read information from virtual drive");
app_gtkmm_set_widget_tooltip(*b, _("Cannot re-read information from virtual drive"));
}
}
@@ -421,16 +427,17 @@ void GscInfoWindow::fill_ui_with_info(bool scan, bool clear_ui, bool clear_tests
// Top label - short device information
{
std::string device = Glib::Markup::escape_text(drive->get_device_with_type());
std::string model = Glib::Markup::escape_text(drive->get_model_name().empty() ? "Unknown model" : drive->get_model_name());
std::string model = Glib::Markup::escape_text(drive->get_model_name().empty() ? _("Unknown model") : drive->get_model_name());
std::string drive_letters = Glib::Markup::escape_text(drive->format_drive_letters(false));
this->set_title("Device Information - " + device + ": " + model + " - GSmartControl");
/// Translators: %1 is device name, %2 is device model.
this->set_title(Glib::ustring::compose(_("Device Information - %1: %2 - GSmartControl"), device, model));
// Gtk::Label* device_name_label = lookup_widget<Gtk::Label*>("device_name_label");
if (device_name_label) {
device_name_label->set_markup(
"<b>Device: </b>" + device + (drive_letters.empty() ? "" : (" (<b>" + drive_letters + "</b>)"))
+ " <b>Model: </b>" + model);
/// Translators: %1 is device name, %2 is drive letters (if not empty), %3 is device model.
device_name_label->set_markup(Glib::ustring::compose(_("<b>Device:</b> %1%2 <b>Model:</b> %3"),
device, (drive_letters.empty() ? "" : (" (<b>" + drive_letters + "</b>)")), model));
}
}
@@ -477,11 +484,11 @@ void GscInfoWindow::clear_ui_info(bool clear_tests_too)
// fill_ui_with_info() will do it all by itself.
{
this->set_title("Device Information - GSmartControl");
this->set_title(_("Device Information - GSmartControl"));
// Gtk::Label* device_name_label = lookup_widget<Gtk::Label*>("device_name_label");
if (device_name_label)
device_name_label->set_text("No data available");
device_name_label->set_text(_("No data available"));
}
{
@@ -595,7 +602,7 @@ void GscInfoWindow::clear_ui_info(bool clear_tests_too)
if (textview) {
// we re-create the buffer to get rid of all the Marks
textview->set_buffer(Gtk::TextBuffer::create());
textview->get_buffer()->set_text("\nNo data available");
textview->get_buffer()->set_text("\n"s + _("No data available"));
}
// tab label
@@ -606,7 +613,7 @@ void GscInfoWindow::clear_ui_info(bool clear_tests_too)
auto* textview = lookup_widget<Gtk::TextView*>("temperature_log_textview");
if (textview) {
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
buffer->set_text("\nNo data available");
buffer->set_text("\n"s + _("No data available"));
}
// tab label
@@ -633,7 +640,7 @@ void GscInfoWindow::clear_ui_info(bool clear_tests_too)
{
if (auto* textview = lookup_widget<Gtk::TextView*>("erc_log_textview")) {
textview->get_buffer()->set_text("\nNo data available");
textview->get_buffer()->set_text("\n"s + _("No data available"));
}
// tab label
@@ -642,7 +649,7 @@ void GscInfoWindow::clear_ui_info(bool clear_tests_too)
{
if (auto* textview = lookup_widget<Gtk::TextView*>("selective_selftest_log_textview")) {
textview->get_buffer()->set_text("\nNo data available");
textview->get_buffer()->set_text("\n"s + _("No data available"));
}
// tab label
@@ -651,7 +658,7 @@ void GscInfoWindow::clear_ui_info(bool clear_tests_too)
{
if (auto* textview = lookup_widget<Gtk::TextView*>("phy_log_textview")) {
textview->get_buffer()->set_text("\nNo data available");
textview->get_buffer()->set_text("\n"s + _("No data available"));
}
// tab label
@@ -660,7 +667,7 @@ void GscInfoWindow::clear_ui_info(bool clear_tests_too)
{
if (auto* textview = lookup_widget<Gtk::TextView*>("directory_log_textview")) {
textview->get_buffer()->set_text("\nNo data available");
textview->get_buffer()->set_text("\n"s + _("No data available"));
}
// tab label
@@ -715,7 +722,7 @@ void GscInfoWindow::on_view_output_button_clicked()
output = this->drive->get_info_output();
}
win->set_text("Smartctl Output", output, true, true);
win->set_text(_("Smartctl Output"), output, true, true);
std::string filename = drive->get_save_filename();
if (!filename.empty())
@@ -737,16 +744,16 @@ void GscInfoWindow::on_save_info_button_clicked()
std::string filename = drive->get_save_filename();
Glib::RefPtr<Gtk::FileFilter> specific_filter = Gtk::FileFilter::create();
specific_filter->set_name("Text Files");
specific_filter->set_name(_("Text Files"));
specific_filter->add_pattern("*.txt");
Glib::RefPtr<Gtk::FileFilter> all_filter = Gtk::FileFilter::create();
all_filter->set_name("All Files");
all_filter->set_name(_("All Files"));
all_filter->add_pattern("*");
#if GTK_CHECK_VERSION(3, 20, 0)
hz::scoped_ptr<GtkFileChooserNative> dialog(gtk_file_chooser_native_new(
"Save Data As...", this->gobj(), GTK_FILE_CHOOSER_ACTION_SAVE, nullptr, nullptr), g_object_unref);
_("Save Data As..."), this->gobj(), GTK_FILE_CHOOSER_ACTION_SAVE, nullptr, nullptr), g_object_unref);
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog.get()), true);
@@ -762,7 +769,7 @@ void GscInfoWindow::on_save_info_button_clicked()
result = gtk_native_dialog_run(GTK_NATIVE_DIALOG(dialog.get()));
#else
Gtk::FileChooserDialog dialog(*this, "Save Data As...",
Gtk::FileChooserDialog dialog(*this, _("Save Data As..."),
Gtk::FILE_CHOOSER_ACTION_SAVE);
// Add response buttons the the dialog
@@ -808,7 +815,7 @@ void GscInfoWindow::on_save_info_button_clicked()
}
std::error_code ec = hz::fs_file_put_contents(hz::fs::u8path(file), data);
if (ec) {
gui_show_error_dialog("Cannot save SMART data to file", ec.message(), this);
gui_show_error_dialog(_("Cannot save SMART data to file"), ec.message(), this);
}
break;
}
@@ -828,7 +835,7 @@ void GscInfoWindow::on_save_info_button_clicked()
void GscInfoWindow::on_close_window_button_clicked()
{
if (drive && drive->get_test_is_active()) { // disallow close if test is active.
gui_show_warn_dialog("Please wait until all tests are finished.", this);
gui_show_warn_dialog(_("Please wait until all tests are finished."), this);
} else {
destroy(this); // deletes this object and nullifies instance
}
@@ -847,8 +854,8 @@ void GscInfoWindow::on_test_type_combo_changed()
//debug_out_error("app", test->get_min_duration_seconds() << "\n");
if (auto* min_duration_label = lookup_widget<Gtk::Label*>("min_duration_label")) {
auto duration = test->get_min_duration_seconds();
min_duration_label->set_text(duration == std::chrono::seconds(-1) ? "N/A"
: (duration.count() == 0 ? "Unknown" : hz::format_time_length(duration)));
min_duration_label->set_text(duration == std::chrono::seconds(-1) ? C_("duration", "N/A")
: (duration.count() == 0 ? C_("duration", "Unknown") : hz::format_time_length(duration)));
}
auto* test_description_textview = lookup_widget<Gtk::TextView*>("test_description_textview");
@@ -962,12 +969,12 @@ void GscInfoWindow::fill_ui_attributes(const std::vector<StorageProperty>& props
Gtk::TreeModelColumn<int32_t> col_id;
model_columns.add(col_id); // we can use the column variable by value after this.
num_tree_cols = app_gtkmm_create_tree_view_column(col_id, *treeview, "ID", "Attribute ID", true);
num_tree_cols = app_gtkmm_create_tree_view_column(col_id, *treeview, _("ID"), _("Attribute ID"), true);
Gtk::TreeModelColumn<Glib::ustring> col_name;
model_columns.add(col_name);
num_tree_cols = app_gtkmm_create_tree_view_column(col_name, *treeview,
"Name", "Attribute name (this is deduced from ID by smartctl and may be incorrect, as it's highly vendor-specific)", true);
_("Name"), _("Attribute name (this is deduced from ID by smartctl and may be incorrect, as it's highly vendor-specific)"), true);
treeview->set_search_column(col_name.index());
auto* cr_name = dynamic_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
if (cr_name)
@@ -976,32 +983,32 @@ void GscInfoWindow::fill_ui_attributes(const std::vector<StorageProperty>& props
Gtk::TreeModelColumn<Glib::ustring> col_failed;
model_columns.add(col_failed);
num_tree_cols = app_gtkmm_create_tree_view_column(col_failed, *treeview,
"Failed", "When failed (that is, the normalized value became equal to or less than threshold)", true, true);
_("Failed"), _("When failed (that is, the normalized value became equal to or less than threshold)"), true, true);
Gtk::TreeModelColumn<std::string> col_value;
model_columns.add(col_value);
num_tree_cols = app_gtkmm_create_tree_view_column(col_value, *treeview,
"Norm-ed value", "Normalized value (highly vendor-specific; converted from Raw value by the drive's firmware)", false);
C_("value", "Normalized"), _("Normalized value (highly vendor-specific; converted from Raw value by the drive's firmware)"), false);
Gtk::TreeModelColumn<std::string> col_worst;
model_columns.add(col_worst);
num_tree_cols = app_gtkmm_create_tree_view_column(col_worst, *treeview,
"Worst", "The worst normalized value recorded for this attribute during the drive's lifetime (with SMART enabled)", false);
C_("value", "Worst"), _("The worst normalized value recorded for this attribute during the drive's lifetime (with SMART enabled)"), false);
Gtk::TreeModelColumn<std::string> col_threshold;
model_columns.add(col_threshold);
num_tree_cols = app_gtkmm_create_tree_view_column(col_threshold, *treeview,
"Threshold", "Threshold for normalized value. Normalized value should be greater than threshold (unless vendor thinks otherwise).", false);
C_("value", "Threshold"), _("Threshold for normalized value. Normalized value should be greater than threshold (unless vendor thinks otherwise)."), false);
Gtk::TreeModelColumn<std::string> col_raw;
model_columns.add(col_raw);
num_tree_cols = app_gtkmm_create_tree_view_column(col_raw, *treeview,
"Raw value", "Raw value as reported by drive. May or may not be sensible.", false);
_("Raw value"), _("Raw value as reported by drive. May or may not be sensible."), false);
Gtk::TreeModelColumn<Glib::ustring> col_type;
model_columns.add(col_type);
num_tree_cols = app_gtkmm_create_tree_view_column(col_type, *treeview,
"Type", "Alarm condition is reached when if normalized value becomes less than or equal to threshold. Type indicates whether it's a signal of drive's pre-failure time or just an old age.", false, true);
_("Type"), _("Alarm condition is reached when normalized value becomes less than or equal to threshold. Type indicates whether it's a signal of drive's pre-failure time or just an old age."), false, true);
// Doesn't carry that much info. Advanced users can look at the flags.
// Gtk::TreeModelColumn<Glib::ustring> col_updated;
@@ -1012,15 +1019,15 @@ void GscInfoWindow::fill_ui_attributes(const std::vector<StorageProperty>& props
Gtk::TreeModelColumn<std::string> col_flag_value;
model_columns.add(col_flag_value);
num_tree_cols = app_gtkmm_create_tree_view_column(col_flag_value, *treeview,
"Flags", "Flags\n\n"
"If given in POSRCK+ format, the presence of each letter indicates that the flag is on.\n"
"P: pre-failure attribute (if the attribute failed, the drive is failing)\n"
"O: updated continuously (as opposed to updated on offline data collection)\n"
"S: speed / performance attribute\n"
"R: error rate\n"
"C: event count\n"
"K: auto-keep\n"
"+: undocumented bits present", false);
_("Flags"), _("Flags") + "\n\n"s
+ Glib::ustring::compose(_("If given in %1 format, the presence of each letter indicates that the flag is on."), "POSRCK+") + "\n"
+ _("P: pre-failure attribute (if the attribute failed, the drive is failing)") + "\n"
+ _("O: updated continuously (as opposed to updated on offline data collection)") + "\n"
+ _("S: speed / performance attribute") + "\n"
+ _("R: error rate") + "\n"
+ _("C: event count") + "\n"
+ _("K: auto-keep") + "\n"
+ _("+: undocumented bits present"), false);
Gtk::TreeModelColumn<Glib::ustring> col_tooltip;
model_columns.add(col_tooltip);
@@ -1108,7 +1115,7 @@ void GscInfoWindow::fill_ui_statistics(const std::vector<StorageProperty>& props
Gtk::TreeModelColumn<Glib::ustring> col_description;
model_columns.add(col_description);
num_tree_cols = app_gtkmm_create_tree_view_column(col_description, *treeview,
"Description", "Entry description", true);
_("Description"), _("Entry description"), true);
treeview->set_search_column(col_description.index());
// Gtk::CellRendererText* cr_name = dynamic_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
// if (cr_name)
@@ -1117,21 +1124,21 @@ void GscInfoWindow::fill_ui_statistics(const std::vector<StorageProperty>& props
Gtk::TreeModelColumn<std::string> col_value;
model_columns.add(col_value);
num_tree_cols = app_gtkmm_create_tree_view_column(col_value, *treeview,
"Value", "Value (can be normalized if 'N' flag is present)", false);
_("Value"), Glib::ustring::compose(_("Value (can be normalized if '%1' flag is present)"), "N"), false);
Gtk::TreeModelColumn<std::string> col_flags;
model_columns.add(col_flags);
num_tree_cols = app_gtkmm_create_tree_view_column(col_flags, *treeview,
"Flags", "Flags\n\n"
"N: value is normalized\n"
"D: supports Device Statistics Notification (DSN)\n"
"C: monitored condition met\n" // Related to DSN? From the specification, it looks like something user-controllable.
"+: undocumented bits present", false);
_("Flags"), _("Flags") + "\n\n"s
+ _("N: value is normalized") + "\n"
+ _("D: supports Device Statistics Notification (DSN)") + "\n"
+ _("C: monitored condition met") + "\n" // Related to DSN? From the specification, it looks like something user-controllable.
+ _("+: undocumented bits present"), false);
Gtk::TreeModelColumn<std::string> col_page_offset;
model_columns.add(col_page_offset);
num_tree_cols = app_gtkmm_create_tree_view_column(col_page_offset, *treeview,
"Page, Offset", "Page and offset of the entry", false);
_("Page, Offset"), _("Page and offset of the entry"), false);
Gtk::TreeModelColumn<Glib::ustring> col_tooltip;
model_columns.add(col_tooltip);
@@ -1223,10 +1230,10 @@ void GscInfoWindow::fill_ui_self_test_info()
row = *(test_combo_model->append());
row[test_combo_col_name] = SelfTest::get_test_name(SelfTest::TestType::immediate_offline);
row[test_combo_col_description] =
"Immediate Offline Test (also known as Immediate Offline Data Collection)"
" is the manual version of Automatic Offline Data Collection, which, if enabled, is automatically run"
" every four hours. If an error occurs during this test, it will be reported in Error Log. Besides that,"
" its effects are visible only in that it updates the \"Offline\" Attribute values.";
_("Immediate Offline Test (also known as Immediate Offline Data Collection)"
" is the manual version of Automatic Offline Data Collection, which, if enabled, is automatically run"
" every four hours. If an error occurs during this test, it will be reported in Error Log. Besides that,"
" its effects are visible only in that it updates the \"Offline\" Attribute values.");
row[test_combo_col_self_test] = test_ioffline;
}
@@ -1235,12 +1242,12 @@ void GscInfoWindow::fill_ui_self_test_info()
row = *(test_combo_model->append());
row[test_combo_col_name] = SelfTest::get_test_name(SelfTest::TestType::short_test);
row[test_combo_col_description] =
"Short self-test consists of a collection of test routines that have the highest chance"
" of detecting drive problems. Its result is reported in the Self-Test Log."
" Note that this test is in no way comprehensive. Its main purpose is to detect totally damaged"
" drives without running the full surface scan."
"\nNote: On some drives this actually runs several consequent tests, which may"
" cause the program to display the test progress incorrectly."; // seagate multi-pass test on 7200.11.
_("Short self-test consists of a collection of test routines that have the highest chance"
" of detecting drive problems. Its result is reported in the Self-Test Log."
" Note that this test is in no way comprehensive. Its main purpose is to detect totally damaged"
" drives without running a full surface scan."
"\nNote: On some drives this actually runs several consequent tests, which may"
" cause the program to display the test progress incorrectly."); // seagate multi-pass test on 7200.11.
row[test_combo_col_self_test] = test_short;
}
@@ -1249,8 +1256,8 @@ void GscInfoWindow::fill_ui_self_test_info()
row = *(test_combo_model->append());
row[test_combo_col_name] = SelfTest::get_test_name(SelfTest::TestType::long_test);
row[test_combo_col_description] =
"Extended self-test examines complete disk surface and performs various test routines"
" built into the drive. Its result is reported in the Self-Test Log.";
_("Extended self-test examines complete disk surface and performs various test routines"
" built into the drive. Its result is reported in the Self-Test Log.");
row[test_combo_col_self_test] = test_long;
}
@@ -1259,7 +1266,7 @@ void GscInfoWindow::fill_ui_self_test_info()
row = *(test_combo_model->append());
row[test_combo_col_name] = SelfTest::get_test_name(SelfTest::TestType::conveyance);
row[test_combo_col_description] =
"Conveyance self-test is intended to identify damage incurred during transporting of the drive.";
_("Conveyance self-test is intended to identify damage incurred during transporting of the drive.");
row[test_combo_col_self_test] = test_conveyance;
}
@@ -1290,7 +1297,7 @@ void GscInfoWindow::fill_ui_self_test_log(const std::vector<StorageProperty>& pr
Gtk::TreeModelColumn<uint32_t> col_num;
model_columns.add(col_num); // we can use the column variable by value after this.
num_tree_cols = app_gtkmm_create_tree_view_column(col_num, *treeview,
"Test #", "Test # (greater may mean newer or older depending on drive model)", true);
_("Test #"), _("Test # (greater may mean newer or older depending on drive model)"), true);
auto* cr_test_num = dynamic_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
if (cr_test_num)
cr_test_num->property_weight() = Pango::WEIGHT_BOLD ;
@@ -1298,28 +1305,28 @@ void GscInfoWindow::fill_ui_self_test_log(const std::vector<StorageProperty>& pr
Gtk::TreeModelColumn<std::string> col_type;
model_columns.add(col_type);
num_tree_cols = app_gtkmm_create_tree_view_column(col_type, *treeview,
"Type", "Type of the test performed", true);
_("Type"), _("Type of the test performed"), true);
treeview->set_search_column(col_type.index());
Gtk::TreeModelColumn<std::string> col_status;
model_columns.add(col_status);
num_tree_cols = app_gtkmm_create_tree_view_column(col_status, *treeview,
"Status", "Test completion status", true);
_("Status"), _("Test completion status"), true);
Gtk::TreeModelColumn<std::string> col_percent;
model_columns.add(col_percent);
num_tree_cols = app_gtkmm_create_tree_view_column(col_percent, *treeview,
"% Completed", "Percentage of the test completed. Instantly-aborted tests have 10%, while unsupported ones _may_ have 100%.", true);
_("% Completed"), _("Percentage of the test completed. Instantly-aborted tests have 10%, while unsupported ones <i>may</i> have 100%."), true, false, true);
Gtk::TreeModelColumn<std::string> col_hours;
model_columns.add(col_hours);
num_tree_cols = app_gtkmm_create_tree_view_column(col_hours, *treeview,
"Lifetime hours", "During which hour of the drive's (powered on) lifetime did the test complete (or abort)", true);
_("Lifetime hours"), _("During which hour of the drive's (powered on) lifetime did the test complete (or abort)"), true);
Gtk::TreeModelColumn<std::string> col_lba;
model_columns.add(col_lba);
num_tree_cols = app_gtkmm_create_tree_view_column(col_lba, *treeview,
"LBA of the first error", "LBA of the first error (if an LBA-related error happened)", true);
_("LBA of the first error"), _("LBA of the first error (if an LBA-related error happened)"), true);
Gtk::TreeModelColumn<Glib::ustring> col_tooltip;
model_columns.add(col_tooltip);
@@ -1401,29 +1408,29 @@ void GscInfoWindow::fill_ui_error_log(const std::vector<StorageProperty>& props)
Gtk::TreeModelColumn<uint32_t> col_num;
model_columns.add(col_num); // we can use the column variable by value after this.
num_tree_cols = app_gtkmm_create_tree_view_column(col_num, *treeview,
"Error #", "Error # in the error log (greater means newer)", true);
_("Error #"), _("Error # in the error log (greater means newer)"), true);
if (auto* cr_name = dynamic_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1)))
cr_name->property_weight() = Pango::WEIGHT_BOLD ;
Gtk::TreeModelColumn<std::string> col_hours;
model_columns.add(col_hours);
num_tree_cols = app_gtkmm_create_tree_view_column(col_hours, *treeview,
"Lifetime hours", "During which hour of the drive's (powered on) lifetime did the error happen.", true);
_("Lifetime hours"), _("During which hour of the drive's (powered on) lifetime did the error happen."), true);
Gtk::TreeModelColumn<std::string> col_state;
model_columns.add(col_state);
num_tree_cols = app_gtkmm_create_tree_view_column(col_state, *treeview,
"State", "Power state of the drive when the error occurred", false);
C_("power", "State"), _("Power state of the drive when the error occurred"), false);
Gtk::TreeModelColumn<Glib::ustring> col_type;
model_columns.add(col_type);
num_tree_cols = app_gtkmm_create_tree_view_column(col_type, *treeview,
"Type", "Type of error", true);
_("Type"), _("Type of error"), true);
Gtk::TreeModelColumn<std::string> col_details;
model_columns.add(col_details);
num_tree_cols = app_gtkmm_create_tree_view_column(col_details, *treeview,
"Details", "Additional details (e.g. LBA where the error occurred, etc...)", true);
_("Details"), _("Additional details (e.g. LBA where the error occurred, etc...)"), true);
Gtk::TreeModelColumn<Glib::ustring> col_tooltip;
model_columns.add(col_tooltip);
@@ -1461,7 +1468,7 @@ void GscInfoWindow::fill_ui_error_log(const std::vector<StorageProperty>& props)
// Add complete error log to textview window.
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
if (buffer) {
buffer->set_text("\nComplete error log:\n\n" + p.get_value<std::string>());
buffer->set_text("\n" + Glib::ustring::compose(_("Complete error log: %1"), "\n\n" + p.get_value<std::string>()));
// set marks so we can scroll to them
@@ -1472,6 +1479,7 @@ void GscInfoWindow::fill_ui_error_log(const std::vector<StorageProperty>& props)
Gtk::TextIter titer = buffer->begin();
Gtk::TextIter match_start, match_end;
// TODO Change this for json
while (titer.forward_search("\nError ", Gtk::TEXT_SEARCH_TEXT_ONLY, match_start, match_end)) {
match_start.forward_char(); // place after newline
match_end.forward_word_end(); // include error number
@@ -1488,7 +1496,7 @@ void GscInfoWindow::fill_ui_error_log(const std::vector<StorageProperty>& props)
} else if (!p.is_value_type<StorageErrorBlock>()) {
label_strings.emplace_back(p.readable_name + ": " + p.format_value(), &p);
if (p.generic_name == "error_log_error_count")
label_strings.back().label += " (Note: The number of entries may be limited to the newest ones)";
label_strings.back().label += " "s + _("(Note: The number of entries may be limited to the newest ones)");
} else {
const auto& eb = p.get_value<StorageErrorBlock>();
@@ -1505,7 +1513,7 @@ void GscInfoWindow::fill_ui_error_log(const std::vector<StorageProperty>& props)
// "No description available" for all of them.
row[col_tooltip] = p.get_description();
row[col_storage] = &p;
row[col_mark_name] = "Error " + hz::number_to_string_locale(eb.error_num);
row[col_mark_name] = Glib::ustring::compose(_("Error %1"), eb.error_num);
}
if (int(p.warning) > int(max_tab_warning))
@@ -1560,7 +1568,7 @@ void GscInfoWindow::fill_ui_temperature_log(const std::vector<StorageProperty>&
continue;
if (p.generic_name == "sct_unsupported" && p.get_value<bool>()) { // only show if unsupported
label_strings.emplace_back("SCT temperature commands not supported.", &p);
label_strings.emplace_back(_("SCT temperature commands not supported."), &p);
if (int(p.warning) > int(max_tab_warning))
max_tab_warning = p.warning;
continue;
@@ -1569,17 +1577,17 @@ void GscInfoWindow::fill_ui_temperature_log(const std::vector<StorageProperty>&
// Note: Don't use property description as a tooltip here. It won't be available if there's no property.
if (p.generic_name == "scttemp_log") {
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
buffer->set_text("\nComplete SCT temperature log:\n\n" + p.get_value<std::string>());
buffer->set_text("\n" + Glib::ustring::compose(_("Complete SCT temperature log: %1"), "\n\n" + p.get_value<std::string>()));
}
}
if (temperature.empty()) {
temperature = "Unknown";
temperature = C_("value", "Unknown");
} else {
temperature += " C";
temperature = Glib::ustring::compose(C_("temperature", "%1 C"), temperature);
}
temp_property.set_description("Current drive temperature in Celsius."); // overrides attribute description
label_strings.emplace_back("Current temperature: <b>" + temperature + "</b>", &temp_property, true);
temp_property.set_description(_("Current drive temperature in Celsius.")); // overrides attribute description
label_strings.emplace_back(Glib::ustring::compose(_("Current temperature: %1"), "<b>" + temperature + "</b>"), &temp_property, true);
if (int(temp_property.warning) > int(max_tab_warning))
max_tab_warning = temp_property.warning;
@@ -1604,11 +1612,11 @@ WarningLevel GscInfoWindow::fill_ui_capabilities(const std::vector<StorageProper
Gtk::TreeModelColumn<int> col_index;
model_columns.add(col_index); // we can use the column variable by value after this.
num_tree_cols = app_gtkmm_create_tree_view_column(col_index, *treeview, "#", "Entry #", true);
num_tree_cols = app_gtkmm_create_tree_view_column(col_index, *treeview, _("#"), _("Entry #"), true);
Gtk::TreeModelColumn<Glib::ustring> col_name;
model_columns.add(col_name);
num_tree_cols = app_gtkmm_create_tree_view_column(col_name, *treeview, "Name", "Name", true);
num_tree_cols = app_gtkmm_create_tree_view_column(col_name, *treeview, _("Name"), _("Name"), true);
treeview->set_search_column(col_name.index());
auto cr_name = dynamic_cast<Gtk::CellRendererText*>(treeview->get_column_cell_renderer(num_tree_cols - 1));
if (cr_name)
@@ -1616,11 +1624,11 @@ WarningLevel GscInfoWindow::fill_ui_capabilities(const std::vector<StorageProper
Gtk::TreeModelColumn<std::string> col_flag_value;
model_columns.add(col_flag_value);
num_tree_cols = app_gtkmm_create_tree_view_column(col_flag_value, *treeview, "Flags", "Flags", false);
num_tree_cols = app_gtkmm_create_tree_view_column(col_flag_value, *treeview, _("Flags"), _("Flags"), false);
Gtk::TreeModelColumn<Glib::ustring> col_str_values;
model_columns.add(col_str_values);
num_tree_cols = app_gtkmm_create_tree_view_column(col_str_values, *treeview, "Capabilities", "Capabilities", false);
num_tree_cols = app_gtkmm_create_tree_view_column(col_str_values, *treeview, _("Capabilities"), _("Capabilities"), false);
Gtk::TreeModelColumn<Glib::ustring> col_tooltip;
model_columns.add(col_tooltip);
@@ -1696,7 +1704,7 @@ WarningLevel GscInfoWindow::fill_ui_error_recovery(const std::vector<StorageProp
// Note: Don't use property description as a tooltip here. It won't be available if there's no property.
if (p.generic_name == "scterc_log") {
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
buffer->set_text("\nComplete SCT Error Recovery Control settings:\n\n" + p.get_value<std::string>());
buffer->set_text("\n" + Glib::ustring::compose(_("Complete SCT Error Recovery Control settings: %1"), "\n\n" + p.get_value<std::string>()));
}
}
@@ -1721,7 +1729,7 @@ WarningLevel GscInfoWindow::fill_ui_selective_self_test_log(const std::vector<St
// Note: Don't use property description as a tooltip here. It won't be available if there's no property.
if (p.generic_name == "SubSection::selective_selftest_log") {
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
buffer->set_text("\nComplete selective self-test log:\n\n" + p.get_value<std::string>());
buffer->set_text("\n" + Glib::ustring::compose(_("Complete selective self-test log: %1"), "\n\n" + p.get_value<std::string>()));
}
}
@@ -1746,7 +1754,7 @@ WarningLevel GscInfoWindow::fill_ui_physical(const std::vector<StorageProperty>&
// Note: Don't use property description as a tooltip here. It won't be available if there's no property.
if (p.generic_name == "sataphy_log") {
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
buffer->set_text("\nComplete phy log:\n\n" + p.get_value<std::string>());
buffer->set_text("\n" + Glib::ustring::compose(_("Complete phy log: %1"), "\n\n" + p.get_value<std::string>()));
}
}
@@ -1771,7 +1779,7 @@ WarningLevel GscInfoWindow::fill_ui_directory(const std::vector<StorageProperty>
// Note: Don't use property description as a tooltip here. It won't be available if there's no property.
if (p.generic_name == "directory_log") {
Glib::RefPtr<Gtk::TextBuffer> buffer = textview->get_buffer();
buffer->set_text("\nComplete directory log:\n\n" + p.get_value<std::string>());
buffer->set_text("\n" + Glib::ustring::compose(_("Complete directory log: %1"), "\n\n" + p.get_value<std::string>()));
}
}
@@ -1805,7 +1813,7 @@ gboolean GscInfoWindow::test_idle_callback(void* data)
}
int8_t rem_percent = self->current_test->get_remaining_percent();
std::string rem_percent_str = (rem_percent == -1 ? "Unknown" : hz::number_to_string_locale(100 - rem_percent));
std::string rem_percent_str = (rem_percent == -1 ? C_("value", "Unknown") : hz::number_to_string_locale(100 - rem_percent));
auto poll_in = self->current_test->get_poll_in_seconds(); // sec
@@ -1822,13 +1830,12 @@ gboolean GscInfoWindow::test_idle_callback(void* data)
auto rem_seconds = self->current_test->get_remaining_seconds();
if (test_completion_progressbar) {
std::string rem_seconds_str = (rem_seconds == std::chrono::seconds(-1) ? "Unknown" : hz::format_time_length(rem_seconds));
std::string rem_seconds_str = (rem_seconds == std::chrono::seconds(-1) ? C_("duration", "Unknown") : hz::format_time_length(rem_seconds));
Glib::ustring bar_str;
if (self->test_error_msg.empty()) {
bar_str = hz::string_sprintf("Test completion: %s%%; ETA: %s",
rem_percent_str.c_str(), rem_seconds_str.c_str());
bar_str = Glib::ustring::compose(_("Test completion: %1%%; ETA: %2"), rem_percent_str, rem_seconds_str);
} else {
bar_str = self->test_error_msg; // better than popup every few seconds
}
@@ -1892,16 +1899,16 @@ gboolean GscInfoWindow::test_idle_callback(void* data)
if (!self->test_error_msg.empty()) {
aborted = true;
severity = StorageSelftestEntry::StatusSeverity::error;
result_msg = "<b>Test aborted: </b>" + self->test_error_msg;
result_msg = Glib::ustring::compose(_("<b>Test aborted:</b> %1"), self->test_error_msg);
} else {
severity = StorageSelftestEntry::get_status_severity(status);
if (status == StorageSelftestEntry::Status::aborted_by_host) {
aborted = true;
result_msg = "<b>Test was manually aborted.</b>"; // it's a StatusSeverity::none message
result_msg = "<b>"s + _("Test was manually aborted.") + "</b>"; // it's a StatusSeverity::none message
} else {
result_msg = "<b>Test result: </b>" + StorageSelftestEntry::get_status_name(status) + ".";
result_msg = Glib::ustring::compose(_("<b>Test result:</b> %1."), StorageSelftestEntry::get_status_name(status));
// It may not reach 100% somehow, so do it manually.
if (test_completion_progressbar)
@@ -1910,7 +1917,7 @@ gboolean GscInfoWindow::test_idle_callback(void* data)
}
if (severity != StorageSelftestEntry::StatusSeverity::none) {
result_msg += "\nCheck the Self-Test Log for more information.";
result_msg += "\n"s + _("Check the Self-Test Log for more information.");
}
@@ -1921,7 +1928,7 @@ gboolean GscInfoWindow::test_idle_callback(void* data)
test_execute_button->set_sensitive(true);
if (test_completion_progressbar)
test_completion_progressbar->set_text(aborted ? "Test aborted" : "Test completed");
test_completion_progressbar->set_text(aborted ? _("Test aborted") : _("Test completed"));
if (auto* test_stop_button = self->lookup_widget<Gtk::Button*>("test_stop_button"))
test_stop_button->set_sensitive(false);
@@ -1977,7 +1984,8 @@ void GscInfoWindow::on_test_execute_button_clicked()
std::string error_msg = test->start(ex); // this runs update() too.
if (!error_msg.empty()) {
gui_show_error_dialog("Cannot run " + SelfTest::get_test_name(test->get_test_type()), error_msg, this);
/// Translators: %1 is test name
gui_show_error_dialog(Glib::ustring::compose(_("Cannot run %1"), SelfTest::get_test_name(test->get_test_type())), error_msg, this);
return;
}
@@ -2038,7 +2046,8 @@ void GscInfoWindow::on_test_stop_button_clicked()
std::string error_msg = current_test->force_stop(ex);
if (!error_msg.empty()) {
gui_show_error_dialog("Cannot stop " + SelfTest::get_test_name(current_test->get_test_type()), error_msg, this);
/// Translators: %1 is test name
gui_show_error_dialog(Glib::ustring::compose(_("Cannot stop %1"), SelfTest::get_test_name(current_test->get_test_type())), error_msg, this);
return;
}
+23 -22
View File
@@ -22,6 +22,7 @@
#include <memory>
#include <cmath>
#include <gtkmm.h>
#include <glibmm/i18n.h>
#include <glib.h> // g_, G*
#ifdef _WIN32
@@ -29,7 +30,7 @@
#include <versionhelpers.h>
#endif
#include "config.h" // VERSION
#include "config.h" // VERSION, PACKAGE
#include "libdebug/libdebug.h" // include full libdebug here (to add domains, etc...)
#include "rconfig/config.h"
@@ -207,25 +208,25 @@ namespace {
static const GOptionEntry arg_entries[] =
{
{ "no-locale", 'l', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &(args.arg_locale),
"Don't use system locale", nullptr },
N_("Don't use system locale"), nullptr },
{ "version", 'V', 0, G_OPTION_ARG_NONE, &(args.arg_version),
"Display version information", nullptr },
N_("Display version information"), nullptr },
{ "no-scan", '\0', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &(args.arg_scan),
"Don't scan devices on startup", nullptr },
N_("Don't scan devices on startup"), nullptr },
{ "no-hide-tabs", '\0', G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &(args.arg_hide_tabs),
"Don't hide non-identity tabs when SMART is disabled. Useful for debugging.", nullptr },
N_("Don't hide non-identity tabs when SMART is disabled. Useful for debugging."), nullptr },
{ "add-virtual", '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &(args.arg_add_virtual),
"Load smartctl data from file, creating a virtual drive. You can specify this option multiple times.", nullptr },
N_("Load smartctl data from file, creating a virtual drive. You can specify this option multiple times."), nullptr },
{ "add-device", '\0', 0, G_OPTION_ARG_FILENAME_ARRAY, &(args.arg_add_device),
"Add this device to device list. The format of the device is \"<device>::<type>::<extra_args>\", where type and extra_args are optional."
N_("Add this device to device list. The format of the device is \"<device>::<type>::<extra_args>\", where type and extra_args are optional."
" This option is useful with --no-scan to list certain drives only. You can specify this option multiple times."
" Example: --add-device /dev/sda --add-device /dev/twa0::3ware,2 --add-device '/dev/sdb::::-T permissive'", nullptr },
" Example: --add-device /dev/sda --add-device /dev/twa0::3ware,2 --add-device '/dev/sdb::::-T permissive'"), nullptr },
#ifndef _WIN32
// X11-specific
{ "gdk-scale", 'l', 0, G_OPTION_ARG_DOUBLE, &(args.arg_gdk_scale),
"The value of GDK_SCALE environment variable (useful when executing with pkexec)", nullptr },
N_("The value of GDK_SCALE environment variable (useful when executing with pkexec)"), nullptr },
{ "gdk-dpi-scale", 'l', 0, G_OPTION_ARG_DOUBLE, &(args.arg_gdk_dpi_scale),
"The value of GDK_DPI_SCALE environment variable (useful when executing with pkexec)", nullptr },
N_("The value of GDK_DPI_SCALE environment variable (useful when executing with pkexec)"), nullptr },
#endif
{ nullptr }
};
@@ -247,20 +248,15 @@ namespace {
bool parsed = static_cast<bool>(g_option_context_parse(context, &argc, &argv, &error));
if (error) {
std::string error_text = "\n" + std::string("Error parsing command-line options: ");
error_text += (error->message ? error->message : "invalid error");
std::string error_text = "\n" + Glib::ustring::compose(_("Error parsing command-line options: %1"), (error->message ? error->message : "invalid error"));
error_text += "\n\n";
g_error_free(error);
#if (GLIB_CHECK_VERSION(2,14,0))
gchar* help_text = g_option_context_get_help(context, true, nullptr);
if (help_text) {
error_text += help_text;
g_free(help_text);
}
#else
error_text += "Exiting.\n";
#endif
std::fprintf(stderr, "%s", error_text.c_str());
}
@@ -274,12 +270,12 @@ namespace {
/// Print application version information
inline void app_print_version_info()
{
std::string versiontext = std::string("\nGSmartControl version ") + VERSION + "\n";
std::string versiontext = "\n" + Glib::ustring::compose(_("GSmartControl version %1"), VERSION) + "\n";
std::string warningtext = std::string("\nWarning: GSmartControl");
warningtext += " comes with ABSOLUTELY NO WARRANTY.\n";
warningtext += "See LICENSE_gsmartcontrol.txt file for details.\n";
warningtext += "\nCopyright (C) 2008 - 2018 Alexander Shaduri <ashaduri" "" "@" "" "" "gmail.com>\n\n";
std::string warningtext = std::string("\n") + _("Warning: GSmartControl comes with ABSOLUTELY NO WARRANTY.\n"
"See LICENSE_gsmartcontrol.txt file for details.") + "\n\n";
/// %1 is years, %2 is email address
warningtext += Glib::ustring::compose(_("Copyright (C) %1 Alexander Shaduri %2"), "2008 - 2018", "<ashaduri\" \"\" \"@\" \"\" \"\" \"gmail.com>") + "\n\n";
std::fprintf(stdout, "%s%s", versiontext.c_str(), warningtext.c_str());
}
@@ -296,6 +292,11 @@ bool app_init_and_loop(int& argc, char**& argv)
hz::env_set_value("GTK_CSD", "0");
#endif
// Set up gettext. This has to be before gtk is initialized.
bindtextdomain(PACKAGE, PACKAGE_LOCALE_DIR);
bind_textdomain_codeset(PACKAGE, "UTF-8");
textdomain(PACKAGE);
// Glib needs the C locale set to system locale for command line args.
// We will reset it later if needed.
hz::locale_c_set(""); // set the current locale to system locale
@@ -431,7 +432,7 @@ bool app_init_and_loop(int& argc, char**& argv)
// This shows up in About dialog gtk.
Glib::set_application_name("GSmartControl"); // should be localized
Glib::set_application_name(_("GSmartControl"));
// Add data file search paths
+93 -90
View File
@@ -13,6 +13,7 @@
#include "local_glibmm.h"
#include <gtkmm.h>
#include <glibmm/i18n.h>
#include <vector>
#include "hz/string_algo.h" // string_split
@@ -46,9 +47,7 @@
// Compiled-in resources
using namespace std::literals;
GscMainWindow::GscMainWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk::Builder> ui)
@@ -95,7 +94,7 @@ GscMainWindow::GscMainWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk::Builder>
// std::string smartctl_def_options = rconfig::get_data<std::string>("system/smartctl_options");
if (smartctl_binary.empty()) {
error_msg = "Smartctl binary is not specified in configuration.";
error_msg = _("Smartctl binary is not specified in configuration.");
show_output_button = false;
break;
}
@@ -105,7 +104,7 @@ GscMainWindow::GscMainWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk::Builder>
SmartctlExecutorGui ex;
ex.create_running_dialog(this);
ex.set_running_msg("Checking if smartctl is executable...");
ex.set_running_msg(_("Checking if smartctl is executable..."));
// ex.set_command(Glib::shell_quote(smartctl_binary), smartctl_def_options + "-V"); // --version
ex.set_command(Glib::shell_quote(smartctl_binary), "-V"); // --version
@@ -117,13 +116,13 @@ GscMainWindow::GscMainWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk::Builder>
std::string output = ex.get_stdout_str();
if (output.empty()) {
error_msg = "Smartctl returned an empty output.";
error_msg = _("Smartctl returned an empty output.");
break;
}
std::string version, version_full;
if (!SmartctlParser::parse_version(output, version, version_full)) {
error_msg = "Smartctl returned invalid output.";
error_msg = _("Smartctl returned invalid output.");
break;
}
@@ -133,7 +132,7 @@ GscMainWindow::GscMainWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk::Builder>
double version_double = 0;
if (hz::string_is_numeric_nolocale<double>(version, version_double, false)) {
if (version_double < minimum_req_version) {
error_msg = "Smartctl version " + version + " found, " + hz::number_to_string_nolocale(minimum_req_version) + " required.";
error_msg = Glib::ustring::compose(_("Smartctl version %1 found, %2 required."), version, hz::number_to_string_nolocale(minimum_req_version));
break;
}
}
@@ -143,8 +142,8 @@ GscMainWindow::GscMainWindow(BaseObjectType* gtkcobj, Glib::RefPtr<Gtk::Builder>
bool smartctl_valid = error_msg.empty();
if (!smartctl_valid) {
gsc_executor_error_dialog_show("There was an error while executing smartctl",
error_msg + "\n\n<i>Please specify the correct smartctl binary in Preferences.</i>",
gsc_executor_error_dialog_show(_("There was an error while executing smartctl"),
error_msg + "\n\n<i>" + _("Please specify the correct smartctl binary in Preferences.") + "</i>",
this, true, show_output_button);
}
@@ -292,74 +291,74 @@ bool GscMainWindow::create_widgets()
// Add actions
actiongroup_main->add(Gtk::Action::create("file_menu", "_File"));
actiongroup_main->add(Gtk::Action::create("file_menu", _("_File")));
action = Gtk::Action::create(APP_ACTION_NAME(action_quit), Gtk::Stock::QUIT);
actiongroup_main->add((action_map[action_quit] = action), Gtk::AccelKey("<control>Q"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_quit));
actiongroup_main->add(Gtk::Action::create("device_menu", "_Device"));
actiongroup_main->add(Gtk::Action::create("device_menu", _("_Device")));
action = Gtk::Action::create(APP_ACTION_NAME(action_view_details), Gtk::Stock::INFO, "_View details",
"View detailed information");
action = Gtk::Action::create(APP_ACTION_NAME(action_view_details), Gtk::Stock::INFO, _("_View details"),
_("View detailed information"));
actiongroup_device->add((action_map[action_view_details] = action), Gtk::AccelKey("<control>V"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_view_details));
action = Gtk::ToggleAction::create(APP_ACTION_NAME(action_enable_smart), "Enable S_MART",
"Toggle SMART status. The status will be preserved at least until reboot (unless you toggle it again).");
action = Gtk::ToggleAction::create(APP_ACTION_NAME(action_enable_smart), _("Enable SMART"),
_("Toggle SMART status. The status will be preserved at least until reboot (unless you toggle it again)."));
lookup_widget<Gtk::CheckButton*>("status_smart_enabled_check")->set_related_action(action);
actiongroup_device->add((action_map[action_enable_smart] = action), Gtk::AccelKey("<control>M"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_enable_smart));
action = Gtk::ToggleAction::create(APP_ACTION_NAME(action_enable_aodc), "Enable Auto O_ffline Data Collection",
"Toggle Automatic Offline Data Collection which will update \"offline\" SMART attributes every four hours");
action = Gtk::ToggleAction::create(APP_ACTION_NAME(action_enable_aodc), _("Enable Auto Offline Data Collection"),
_("Toggle Automatic Offline Data Collection which will update \"offline\" SMART attributes every four hours"));
lookup_widget<Gtk::CheckButton*>("status_aodc_enabled_check")->set_related_action(action);
actiongroup_device->add((action_map[action_enable_aodc] = action), Gtk::AccelKey("<control>F"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_enable_aodc));
action = Gtk::Action::create(APP_ACTION_NAME(action_reread_device_data), Gtk::Stock::REFRESH, "R_e-read Data",
"Re-read basic SMART data");
action = Gtk::Action::create(APP_ACTION_NAME(action_reread_device_data), Gtk::Stock::REFRESH, _("Re-read Data"),
_("Re-read basic SMART data"));
actiongroup_device->add((action_map[action_reread_device_data] = action), Gtk::AccelKey("<control>E"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_reread_device_data));
action = Gtk::Action::create(APP_ACTION_NAME(action_perform_tests), "Perform _Tests...",
"Perform various self-tests on the drive");
action = Gtk::Action::create(APP_ACTION_NAME(action_perform_tests), _("Perform _Tests..."),
_("Perform various self-tests on the drive"));
actiongroup_device->add((action_map[action_perform_tests] = action), Gtk::AccelKey("<control>T"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_perform_tests));
action = Gtk::Action::create(APP_ACTION_NAME(action_remove_device), Gtk::Stock::REMOVE, "Re_move Added Device",
"Remove previously added device");
action = Gtk::Action::create(APP_ACTION_NAME(action_remove_device), Gtk::Stock::REMOVE, _("Re_move Added Device"),
_("Remove previously added device"));
actiongroup_device->add((action_map[action_remove_device] = action), Gtk::AccelKey("<control>W"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_remove_device));
action = Gtk::Action::create(APP_ACTION_NAME(action_remove_virtual_device), Gtk::Stock::REMOVE, "Re_move Virtual Device",
"Remove previously loaded virtual device");
action = Gtk::Action::create(APP_ACTION_NAME(action_remove_virtual_device), Gtk::Stock::REMOVE, _("Re_move Virtual Device"),
_("Remove previously loaded virtual device"));
actiongroup_device->add((action_map[action_remove_virtual_device] = action), Gtk::AccelKey("Delete"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_remove_virtual_device));
// ---
action = Gtk::Action::create(APP_ACTION_NAME(action_add_device), Gtk::Stock::OPEN, "_Add Device...",
"Manually add device to device list");
action = Gtk::Action::create(APP_ACTION_NAME(action_add_device), Gtk::Stock::OPEN, _("_Add Device..."),
_("Manually add device to device list"));
actiongroup_main->add((action_map[action_add_device] = action), Gtk::AccelKey("<control>D"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_add_device));
action = Gtk::Action::create(APP_ACTION_NAME(action_load_virtual), Gtk::Stock::OPEN, "L_oad Smartctl Output as Virtual Device...",
"Load smartctl output from a text file as a read-only virtual device");
action = Gtk::Action::create(APP_ACTION_NAME(action_load_virtual), Gtk::Stock::OPEN, _("_Load Smartctl Output as Virtual Device..."),
_("Load smartctl output from a text file as a read-only virtual device"));
actiongroup_main->add((action_map[action_load_virtual] = action), Gtk::AccelKey("<control>O"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_load_virtual));
action = Gtk::Action::create(APP_ACTION_NAME(action_rescan_devices), Gtk::Stock::REFRESH, "_Re-scan Device List",
"Re-scan device list");
action = Gtk::Action::create(APP_ACTION_NAME(action_rescan_devices), Gtk::Stock::REFRESH, _("_Re-scan Device List"),
_("Re-scan device list"));
actiongroup_main->add((action_map[action_rescan_devices] = action), Gtk::AccelKey("<control>R"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_rescan_devices));
actiongroup_main->add(Gtk::Action::create("options_menu", "_Options"));
actiongroup_main->add(Gtk::Action::create("options_menu", _("_Options")));
action = Gtk::Action::create(APP_ACTION_NAME(action_executor_log), "View Execution Log");
action = Gtk::Action::create(APP_ACTION_NAME(action_executor_log), _("View Execution Log"));
actiongroup_main->add((action_map[action_executor_log] = action),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_executor_log));
action = Gtk::Action::create(APP_ACTION_NAME(action_update_drivedb), "Update Drive Database");
action = Gtk::Action::create(APP_ACTION_NAME(action_update_drivedb), _("Update Drive Database"));
actiongroup_main->add((action_map[action_update_drivedb] = action),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_update_drivedb));
@@ -367,13 +366,13 @@ bool GscMainWindow::create_widgets()
actiongroup_main->add((action_map[action_preferences] = action), Gtk::AccelKey("<alt>P"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_preferences));
actiongroup_main->add(Gtk::Action::create("help_menu", "_Help"));
actiongroup_main->add(Gtk::Action::create("help_menu", _("_Help")));
action = Gtk::Action::create(APP_ACTION_NAME(action_online_documentation), Gtk::Stock::HELP);
actiongroup_main->add((action_map[action_online_documentation] = action), Gtk::AccelKey("F1"),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_online_documentation));
action = Gtk::Action::create(APP_ACTION_NAME(action_support), "Support");
action = Gtk::Action::create(APP_ACTION_NAME(action_support), _("Support"));
actiongroup_main->add((action_map[action_support] = action),
sigc::bind(sigc::mem_fun(*this, &GscMainWindow::on_action_activated), action_support));
@@ -438,21 +437,21 @@ bool GscMainWindow::create_widgets()
// create and add labels
auto* name_label_box = lookup_widget<Gtk::Box*>("status_name_label_hbox");
name_label = Gtk::manage(new Gtk::Label("No drive selected", Gtk::ALIGN_START));
name_label = Gtk::manage(new Gtk::Label(_("No drive selected"), Gtk::ALIGN_START));
name_label->set_line_wrap(true);
name_label->set_selectable(true);
name_label->show();
name_label_box->pack_start(*name_label, true, true);
auto* health_label_box = lookup_widget<Gtk::Box*>("status_health_label_hbox");
health_label = Gtk::manage(new Gtk::Label("No drive selected", Gtk::ALIGN_START));
health_label = Gtk::manage(new Gtk::Label(_("No drive selected"), Gtk::ALIGN_START));
health_label->set_line_wrap(true);
health_label->set_selectable(true);
health_label->show();
health_label_box->pack_start(*health_label, true, true);
auto* family_label_box = lookup_widget<Gtk::Box*>("status_family_label_hbox");
family_label = Gtk::manage(new Gtk::Label("No drive selected", Gtk::ALIGN_START));
family_label = Gtk::manage(new Gtk::Label(_("No drive selected"), Gtk::ALIGN_START));
family_label->set_line_wrap(true);
family_label->set_selectable(true);
family_label->show();
@@ -471,9 +470,9 @@ namespace {
int status = 0;
{
Gtk::MessageDialog dialog(parent,
"\nOne of the drives is performing a test. Do you really want to quit?\n\n"
"<small>The test will continue to run in the background, but you won't be"
" able to monitor it using GSmartControl.</small>",
"\n"s + _("One of the drives is performing a test. Do you really want to quit?")
+ "\n\n<small>" + _("The test will continue to run in the background, but you won't be"
" able to monitor it using GSmartControl.") + "</small>",
true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true);
status = dialog.run();
}
@@ -653,7 +652,7 @@ void GscMainWindow::on_action_enable_smart_toggled(Gtk::ToggleAction* action)
std::string error_msg = drive->set_smart_enabled(toggle_active, ex); // run it with GUI support
if (!error_msg.empty()) {
std::string error_header = (toggle_active ? "Cannot enable SMART" : "Cannot disable SMART");
std::string error_header = (toggle_active ? _("Cannot enable SMART") : _("Cannot disable SMART"));
gsc_executor_error_dialog_show(error_header, error_msg, this);
}
@@ -685,21 +684,21 @@ void GscMainWindow::on_action_enable_aodc_toggled(Gtk::ToggleAction* action)
int response = 0;
{ // the dialog hides at the end of scope
Gtk::MessageDialog dialog(*this, "\nAutomatic Offline Data Collection status could not be determined.\n"
"\n<big>Do you want to enable or disable it?</big>\n",
Gtk::MessageDialog dialog(*this, "\n"s + _("Automatic Offline Data Collection status could not be determined.\n"
"\n<big>Do you want to enable or disable it?</big>") + "\n",
true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_NONE, true); // markup, modal
Gtk::Button dismiss_button("Dis_miss", true);
Gtk::Button dismiss_button(_("Dis_miss"), true);
dismiss_button.set_image(*Gtk::manage(new Gtk::Image(Gtk::Stock::CANCEL, Gtk::ICON_SIZE_BUTTON)));
dismiss_button.show_all();
dialog.add_action_widget(dismiss_button, Gtk::RESPONSE_CANCEL);
Gtk::Button disable_button("_Disable", true);
Gtk::Button disable_button(_("_Disable"), true);
disable_button.set_image(*Gtk::manage(new Gtk::Image(Gtk::Stock::NO, Gtk::ICON_SIZE_BUTTON)));
disable_button.show_all();
dialog.add_action_widget(disable_button, Gtk::RESPONSE_NO);
Gtk::Button enable_button("_Enable", true);
Gtk::Button enable_button(_("_Enable"), true);
enable_button.set_image(*Gtk::manage(new Gtk::Image(Gtk::Stock::YES, Gtk::ICON_SIZE_BUTTON)));
enable_button.set_can_default(true);
enable_button.show_all();
@@ -734,13 +733,13 @@ void GscMainWindow::on_action_enable_aodc_toggled(Gtk::ToggleAction* action)
std::string error_msg = drive->set_aodc_enabled(enable_aodc, ex); // run it with GUI support
if (!error_msg.empty()) {
std::string error_header = (enable_aodc ? "Cannot enable Automatic Offline Data Collection"
: "Cannot disable Automatic Offline Data Collection");
std::string error_header = (enable_aodc ? _("Cannot enable Automatic Offline Data Collection")
: _("Cannot disable Automatic Offline Data Collection"));
gsc_executor_error_dialog_show(error_header, error_msg, this);
} else { // tell the user, because there's no other feedback
gui_show_info_dialog((enable_aodc ? "Automatic Offline Data Collection enabled."
: "Automatic Offline Data Collection disabled."), this);
gui_show_info_dialog((enable_aodc ? _("Automatic Offline Data Collection enabled.")
: _("Automatic Offline Data Collection disabled.")), this);
}
return;
@@ -758,8 +757,8 @@ void GscMainWindow::on_action_enable_aodc_toggled(Gtk::ToggleAction* action)
std::string error_msg = drive->set_aodc_enabled(toggle_active, ex); // run it with GUI support
if (!error_msg.empty()) {
std::string error_header = (toggle_active ? "Cannot enable Automatic Offline Data Collection"
: "Cannot disable Automatic Offline Data Collection");
std::string error_header = (toggle_active ? _("Cannot enable Automatic Offline Data Collection")
: _("Cannot disable Automatic Offline Data Collection"));
gsc_executor_error_dialog_show(error_header, error_msg, this);
}
@@ -785,7 +784,7 @@ void GscMainWindow::on_action_reread_device_data()
// the icon will be updated through drive's signal_changed callback.
if (!error_msg.empty()) {
gsc_executor_error_dialog_show("Cannot retrieve SMART data", error_msg, this);
gsc_executor_error_dialog_show(_("Cannot retrieve SMART data"), error_msg, this);
}
}
}
@@ -913,20 +912,24 @@ void GscMainWindow::update_status_widgets()
StorageDevicePtr drive = iconview->get_selected_drive();
if (!drive) {
if (name_label)
name_label->set_text("No drive selected");
name_label->set_text(_("No drive selected"));
if (health_label)
health_label->set_text("No drive selected");
health_label->set_text(_("No drive selected"));
if (family_label)
family_label->set_text("No drive selected");
family_label->set_text(_("No drive selected"));
// if (statusbar)
// statusbar->pop();
return;
}
std::string device = Glib::Markup::escape_text(drive->get_is_virtual() ? ("Virtual: " + drive->get_virtual_filename()) : drive->get_device_with_type());
/// Translators: %1 is filename
std::string device = Glib::Markup::escape_text(drive->get_is_virtual()
? Glib::ustring::compose(_("Virtual: %1"), drive->get_virtual_filename()) : Glib::ustring(drive->get_device_with_type()));
std::string size = Glib::Markup::escape_text(drive->get_device_size_str());
std::string model = Glib::Markup::escape_text(drive->get_model_name().empty() ? std::string("Unknown model") : drive->get_model_name());
std::string family = Glib::Markup::escape_text(drive->get_family_name().empty() ? "Unknown" : drive->get_family_name());
std::string model = Glib::Markup::escape_text(drive->get_model_name().empty()
? std::string(_("Unknown model")) : drive->get_model_name());
std::string family = Glib::Markup::escape_text(drive->get_family_name().empty()
? C_("model_family", "Unknown") : drive->get_family_name());
std::string family_fallback = Glib::Markup::escape_text(drive->get_family_name().empty() ? model : drive->get_family_name());
std::string drive_letters_str = Glib::Markup::escape_text(drive->format_drive_letters(false));
@@ -954,12 +957,12 @@ void GscMainWindow::update_status_widgets()
if (health_prop.warning != WarningLevel::none) {
std::string tooltip_str = storage_property_get_warning_reason(health_prop)
+ "\n\nView details for more information.";
+ "\n\n" + _("View details for more information.");
app_gtkmm_set_widget_tooltip(*health_label, tooltip_str, true);
}
} else {
health_label->set_text("Unknown");
health_label->set_text(C_("health_status", "Unknown"));
}
}
@@ -991,7 +994,7 @@ void GscMainWindow::rescan_devices()
int status = 0;
{
Gtk::MessageDialog dialog(*this,
"\nThis operation may abort any running tests. Do you wish to continue?",
"\n"s + _("This operation may abort any running tests. Do you wish to continue?"),
true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true);
status = dialog.run();
}
@@ -1036,9 +1039,9 @@ void GscMainWindow::rescan_devices()
for (const auto& fetch_output : fetch_outputs) {
// debug_out_error("app", DBG_FUNC_MSG << fetch_outputs[i] << "\n");
if (app_pcre_match("/Smartctl open device.+Permission denied/mi", fetch_output)) {
gsc_executor_error_dialog_show("An error occurred while scanning the system",
"It seems that smartctl doesn't have enough permissions to access devices.\n"
"<small>See \"Resolving Permission Problems\" in Help menu for possible solutions.</small>", this, true, true);
gsc_executor_error_dialog_show(_("An error occurred while scanning the system"),
_("It seems that smartctl doesn't have enough permissions to access devices.\n"
"<small>See \"Permission Problems\" section of the documentation, accessible through the Help menu.</small>"), this, true, true);
error = true;
break;
}
@@ -1046,7 +1049,7 @@ void GscMainWindow::rescan_devices()
if (!error && !error_msg.empty()) { // generic scan error. smartctl errors are not reported during scan at all.
// we don't show output button here
gsc_executor_error_dialog_show("An error occurred while scanning the system",
gsc_executor_error_dialog_show(_("An error occurred while scanning the system"),
error_msg, this, false, false);
// error = true;
@@ -1077,7 +1080,7 @@ void GscMainWindow::run_update_drivedb()
auto smartctl_binary = get_smartctl_binary();
if (smartctl_binary.empty()) {
gui_show_error_dialog("Error Updating Drive Database", "Smartctl binary is not specified in configuration.", this);
gui_show_error_dialog(_("Error Updating Drive Database"), _("Smartctl binary is not specified in configuration."), this);
return;
}
@@ -1096,7 +1099,7 @@ void GscMainWindow::run_update_drivedb()
Glib::spawn_command_line_async(update_binary);
}
catch(Glib::Error& e) {
gui_show_error_dialog("Error Updating Drive Database", e.what(), this);
gui_show_error_dialog(_("Error Updating Drive Database"), e.what(), this);
}
}
@@ -1107,8 +1110,8 @@ bool GscMainWindow::add_device(const std::string& file, const std::string& type_
#ifndef _WIN32 // win32 doesn't have device files, so skip the check
std::error_code ec;
if (!hz::fs::exists(hz::fs::u8path(file), ec)) {
gui_show_error_dialog("Cannot add device",
(ec.message().empty() ? std::string("Device \"" + file + "\" doesn't exist.") : ec.message()), this);
gui_show_error_dialog(_("Cannot add device"),
(ec.message().empty() ? Glib::ustring::compose(_("Device \"%1\" doesn't exist."), file).raw() : ec.message()), this);
return false;
}
#endif
@@ -1126,7 +1129,7 @@ bool GscMainWindow::add_device(const std::string& file, const std::string& type_
StorageDetector sd;
std::string error_msg = sd.fetch_basic_data(tmp_drives, ex_factory, true); // return its first error
if (!error_msg.empty()) {
gsc_executor_error_dialog_show("An error occurred while adding the device", error_msg, this);
gsc_executor_error_dialog_show(_("An error occurred while adding the device"), error_msg, this);
} else {
this->drives.push_back(drive);
@@ -1145,7 +1148,7 @@ bool GscMainWindow::add_virtual_drive(const std::string& file)
auto ec = hz::fs_file_get_contents(hz::fs::u8path(file), output, max_size);
if (ec) {
debug_out_warn("app", "Cannot open virtual drive file \"" << file << "\": " << ec.message() << "\n");
gui_show_error_dialog("Cannot load data file", ec.message(), this);
gui_show_error_dialog(_("Cannot load data file"), ec.message(), this);
return false;
}
@@ -1158,7 +1161,7 @@ bool GscMainWindow::add_virtual_drive(const std::string& file)
std::string error_msg = drive->parse_data(); // this will set the type and add the properties
if (!error_msg.empty()) {
gui_show_error_dialog("Cannot interpret SMART data", error_msg, this);
gui_show_error_dialog(_("Cannot interpret SMART data"), error_msg, this);
return false;
}
@@ -1188,7 +1191,7 @@ GscInfoWindow* GscMainWindow::show_device_info_window(const StorageDevicePtr& dr
{
// if a test is being run on it, disallow.
if (drive->get_test_is_active()) {
gui_show_warn_dialog("Please wait until the test is finished on this drive.", this);
gui_show_warn_dialog(_("Please wait until the test is finished on this drive."), this);
return nullptr;
}
@@ -1201,9 +1204,9 @@ GscInfoWindow* GscMainWindow::show_device_info_window(const StorageDevicePtr& dr
// the error one, and we don't want that.
{
Gtk::MessageDialog dialog(*this,
"\nThis drive has SMART disabled. Do you want to enable it?\n\n"
"<small>SMART will stay enabled at least until you reboot your computer.\n"
"See \"How to Enable SMART Permanently\" in Help menu for more information.</small>",
"\n"s + _("This drive has SMART disabled. Do you want to enable it?") + "\n\n"
+ "<small>" + _("SMART will stay enabled at least until you reboot your computer.") + "\n"
+ _("See \"Enable SMART Permanently\" section of the documentation, accessible through the Help menu.") + "</small>",
true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true);
status = dialog.run();
@@ -1211,11 +1214,11 @@ GscInfoWindow* GscMainWindow::show_device_info_window(const StorageDevicePtr& dr
if (status == Gtk::RESPONSE_YES) {
std::shared_ptr<SmartctlExecutorGui> ex(new SmartctlExecutorGui());
ex->create_running_dialog(this, "Running %s on " + drive->get_device_with_type() + "...");
ex->create_running_dialog(this, Glib::ustring::compose(_("Running {command} on %1..."), drive->get_device_with_type()));
std::string error_msg = drive->set_smart_enabled(true, ex); // run it with GUI support
if (!error_msg.empty()) {
gsc_executor_error_dialog_show("Cannot enable SMART", error_msg, this);
gsc_executor_error_dialog_show(_("Cannot enable SMART"), error_msg, this);
}
}
}
@@ -1225,11 +1228,11 @@ GscInfoWindow* GscMainWindow::show_device_info_window(const StorageDevicePtr& dr
// Parse non-virtual, smart-supporting drives here.
if (!drive->get_is_virtual() && drive->get_smart_status() != StorageDevice::Status::unsupported) {
std::shared_ptr<SmartctlExecutorGui> ex(new SmartctlExecutorGui());
ex->create_running_dialog(this, "Running %s on " + drive->get_device_with_type() + "...");
ex->create_running_dialog(this, Glib::ustring::compose(_("Running {command} on %1..."), drive->get_device_with_type()));
std::string error_msg = drive->fetch_data_and_parse(ex); // run it with GUI support
if (!error_msg.empty()) {
gsc_executor_error_dialog_show("Cannot retrieve SMART data", error_msg, this);
gsc_executor_error_dialog_show(_("Cannot retrieve SMART data"), error_msg, this);
return nullptr;
}
}
@@ -1239,8 +1242,8 @@ GscInfoWindow* GscMainWindow::show_device_info_window(const StorageDevicePtr& dr
// usb devices), only very basic info is available and there's no point
// in showing this window. - for both virtual and non-virtual.
if (drive->get_parse_status() == StorageDevice::ParseStatus::none) {
gsc_no_info_dialog_show("No additional information is available for this drive.",
"", this, false, drive->get_info_output(), "Smartctl Output", drive->get_save_filename());
gsc_no_info_dialog_show(_("No additional information is available for this drive."),
"", this, false, drive->get_info_output(), _("Smartctl Output"), drive->get_save_filename());
return nullptr;
}
@@ -1289,16 +1292,16 @@ void GscMainWindow::show_load_virtual_file_chooser()
int result = 0;
Glib::RefPtr<Gtk::FileFilter> specific_filter = Gtk::FileFilter::create();
specific_filter->set_name("Text Files");
specific_filter->set_name(_("Text Files"));
specific_filter->add_pattern("*.txt");
Glib::RefPtr<Gtk::FileFilter> all_filter = Gtk::FileFilter::create();
all_filter->set_name("All Files");
all_filter->set_name(_("All Files"));
all_filter->add_pattern("*");
#if GTK_CHECK_VERSION(3, 20, 0)
hz::scoped_ptr<GtkFileChooserNative> dialog(gtk_file_chooser_native_new(
"Load Data From...", this->gobj(), GTK_FILE_CHOOSER_ACTION_OPEN, nullptr, nullptr), g_object_unref);
_("Load Data From..."), this->gobj(), GTK_FILE_CHOOSER_ACTION_OPEN, nullptr, nullptr), g_object_unref);
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog.get()), specific_filter->gobj());
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog.get()), all_filter->gobj());
@@ -1312,7 +1315,7 @@ void GscMainWindow::show_load_virtual_file_chooser()
result = gtk_native_dialog_run(GTK_NATIVE_DIALOG(dialog.get()));
#else
Gtk::FileChooserDialog dialog(*this, "Load Data From...",
Gtk::FileChooserDialog dialog(*this, _("Load Data From..."),
Gtk::FILE_CHOOSER_ACTION_OPEN);
// Add response buttons the the dialog
+28 -25
View File
@@ -13,6 +13,7 @@
#define GSC_MAIN_WINDOW_ICONVIEW_H
#include <gtkmm.h>
#include <glibmm/i18n.h>
#include <vector>
#include <cmath> // std::floor
#include <unordered_map>
@@ -50,12 +51,12 @@ class GscMainWindowIconView : public Gtk::IconView {
static std::string get_message_string(Message type)
{
static const std::unordered_map<Message, std::string> m {
{Message::none, "[error - invalid message]"},
{Message::scan_disabled, "Automatic scanning is disabled.\nPress Ctrl+R to scan manually."},
{Message::scanning, "Scanning system, please wait..."},
{Message::no_drives_found, "No drives found."},
{Message::no_smartctl, "Please specify the correct smartctl binary in\nPreferences and press Ctrl-R to re-scan."},
{Message::please_rescan, "Preferences changed.\nPress Ctrl-R to re-scan."},
{Message::none, _("[error - invalid message]")},
{Message::scan_disabled, _("Automatic scanning is disabled.\nPress Ctrl+R to scan manually.")},
{Message::scanning, _("Scanning system, please wait...")},
{Message::no_drives_found, _("No drives found.")},
{Message::no_smartctl, _("Please specify the correct smartctl binary in\nPreferences and press Ctrl-R to re-scan.")},
{Message::please_rescan, _("Preferences changed.\nPress Ctrl-R to re-scan.")},
};
if (auto iter = m.find(type); iter != m.end()) {
return iter->second;
@@ -271,11 +272,11 @@ class GscMainWindowIconView : public Gtk::IconView {
std::string name; // = "<big>" + drive->get_device_with_type() + " </big>\n";
Glib::ustring drive_letters = Glib::Markup::escape_text(drive->format_drive_letters(false));
if (drive_letters.empty()) {
drive_letters = "not mounted";
drive_letters = C_("media", "not mounted");
}
Glib::ustring drive_letters_with_volname = Glib::Markup::escape_text(drive->format_drive_letters(true));
if (drive_letters_with_volname.empty()) {
drive_letters_with_volname = "not mounted";
drive_letters_with_volname = C_("media", "not mounted");
}
// note: if this wraps, it becomes left-aligned in gtk <= 2.10.
@@ -305,25 +306,25 @@ class GscMainWindowIconView : public Gtk::IconView {
if (drive->get_is_virtual()) {
std::string vfile = drive->get_virtual_filename();
tooltip_strs.push_back("Loaded from: " + (vfile.empty() ? "[empty]" : Glib::Markup::escape_text(vfile)));
tooltip_strs.push_back(Glib::ustring::compose(_("Loaded from: %1"), (vfile.empty() ? (Glib::ustring("[") + C_("name", "empty") + "]") : Glib::Markup::escape_text(vfile))));
if (!scan_time_prop.empty() && !scan_time_prop.get_value<std::string>().empty()) {
tooltip_strs.push_back("Scanned on: " + Glib::Markup::escape_text(scan_time_prop.get_value<std::string>()));
tooltip_strs.push_back(Glib::ustring::compose(_("Scanned on: "), Glib::Markup::escape_text(scan_time_prop.get_value<std::string>())));
}
} else {
tooltip_strs.push_back("Device: <b>" + Glib::Markup::escape_text(drive->get_device_with_type()) + "</b>");
tooltip_strs.push_back(Glib::ustring::compose(_("Device: %1"), "<b>" + Glib::Markup::escape_text(drive->get_device_with_type()) + "</b>"));
}
#ifdef _WIN32
tooltip_strs.push_back("Drive letters: <b>" + drive_letters_with_volname + "</b>");
tooltip_strs.push_back(Glib::ustring::compose(_("Drive letters: %1"), "<b>" + drive_letters_with_volname + "</b>"));
#endif
if (!drive->get_serial_number().empty()) {
tooltip_strs.push_back("Serial number: <b>" + Glib::Markup::escape_text(drive->get_serial_number()) + "</b>");
tooltip_strs.push_back(Glib::ustring::compose(_("Serial number: %1"), "<b>" + Glib::Markup::escape_text(drive->get_serial_number()) + "</b>"));
}
tooltip_strs.push_back("SMART status: <b>"
+ StorageDevice::get_status_name(drive->get_smart_status()) + "</b>");
tooltip_strs.push_back("Automatic Offline Data Collection status: <b>"
+ StorageDevice::get_status_name(drive->get_aodc_status()) + "</b>");
tooltip_strs.push_back(Glib::ustring::compose(_("SMART status: %1"),
"<b>" + StorageDevice::get_status_name(drive->get_smart_status()) + "</b>"));
tooltip_strs.push_back(Glib::ustring::compose(_("Automatic Offline Data Collection status: %1"),
"<b>" + StorageDevice::get_status_name(drive->get_aodc_status()) + "</b>"));
std::string tooltip_str = hz::string_join(tooltip_strs, '\n');
@@ -365,7 +366,7 @@ class GscMainWindowIconView : public Gtk::IconView {
}
tooltip_str += "\n\n" + storage_property_get_warning_reason(health_prop)
+ "\n\nView details for more information.";
+ "\n\n" + _("View details for more information.");
}
@@ -396,8 +397,9 @@ class GscMainWindowIconView : public Gtk::IconView {
/// Remove selected drive entry
void remove_selected_drive()
{
if (this->get_selected_items().size()) {
Gtk::TreePath model_path = *(this->get_selected_items().begin());
const auto& selected_items = this->get_selected_items();
if (!selected_items.empty()) {
Gtk::TreePath model_path = *(selected_items.begin());
this->remove_entry(model_path);
}
}
@@ -424,9 +426,10 @@ class GscMainWindowIconView : public Gtk::IconView {
/// Get selected drive
StorageDevicePtr get_selected_drive()
{
StorageDevicePtr drive = 0;
if (this->get_selected_items().size()) {
Gtk::TreePath model_path = *(this->get_selected_items().begin());
StorageDevicePtr drive;
const auto& selected_items = this->get_selected_items();
if (!selected_items.empty()) {
Gtk::TreePath model_path = *(selected_items.begin());
Gtk::TreeModel::Row row = *(ref_list_model->get_iter(model_path));
drive = row[col_drive_ptr];
}
@@ -439,7 +442,7 @@ class GscMainWindowIconView : public Gtk::IconView {
Gtk::TreePath get_path_by_drive(StorageDevice* drive)
{
Gtk::TreeNodeChildren children = ref_list_model->children();
for (auto row : children) {
for (const auto& row : children) {
// convert iter to row (iter is row's base, but can we cast it?)
if (drive == row.get_value(col_drive_ptr).get())
return ref_list_model->get_path(row);
@@ -506,7 +509,7 @@ class GscMainWindowIconView : public Gtk::IconView {
if (tpath.gobj() && !tpath.empty()) { // without gobj() check gtkmm 2.6 (but not 2.12) prints lots of errors
// move keyboard focus to the icon (just as left-click does)
Gtk::CellRenderer* cell = 0;
Gtk::CellRenderer* cell = nullptr;
if (this->get_cursor(cell) && cell) {
// gtkmm's set_cursor() is undefined (but declared) in 2.8, so use gtk variant.
gtk_icon_view_set_cursor(GTK_ICON_VIEW(this->gobj()), tpath.gobj(), cell->gobj(), false);
+21 -18
View File
@@ -15,6 +15,7 @@
#include <map>
#include <type_traits> // std::decay_t
#include <gtkmm.h>
#include <glibmm/i18n.h>
#include <gdk/gdk.h> // GDK_KEY_Escape
#include "hz/fs_ns.h"
@@ -29,6 +30,8 @@
using namespace std::literals;
/// Device Options tree view of the Preferences window
class GscPreferencesDeviceOptionsTreeView : public Gtk::TreeView {
@@ -45,11 +48,11 @@ class GscPreferencesDeviceOptionsTreeView : public Gtk::TreeView {
// Type may hold "<all>", while Type Real is "".
model_columns.add(col_device);
this->append_column("Device", col_device);
this->append_column(_("Device"), col_device);
this->set_search_column(col_device.index());
model_columns.add(col_type);
this->append_column("Type", col_type);
this->append_column(_("Type"), col_type);
model_columns.add(col_parameters);
model_columns.add(col_device_real);
@@ -89,8 +92,8 @@ class GscPreferencesDeviceOptionsTreeView : public Gtk::TreeView {
void add_new_row(const std::string& device, const std::string& type, const std::string& params, bool select = true)
{
Gtk::TreeRow row = *(model->append());
row[col_device] = (device.empty() ? "<empty>" : device);
row[col_type] = (type.empty() ? "<all>" : type);
row[col_device] = (device.empty() ? "<"s + C_("name", "empty") + ">" : device);
row[col_type] = (type.empty() ? "<"s + C_("types", "all") + ">" : type);
row[col_parameters] = params;
row[col_device_real] = device;
row[col_type_real] = type;
@@ -105,7 +108,7 @@ class GscPreferencesDeviceOptionsTreeView : public Gtk::TreeView {
{
if (this->get_selection()->count_selected_rows()) {
Gtk::TreeRow row = *(this->get_selection()->get_selected());
row[col_device] = (device.empty() ? "<empty>" : device);
row[col_device] = (device.empty() ? "<"s + C_("name", "empty") + ">" : device);
row[col_device_real] = device;
}
}
@@ -116,7 +119,7 @@ class GscPreferencesDeviceOptionsTreeView : public Gtk::TreeView {
{
if (this->get_selection()->count_selected_rows()) {
Gtk::TreeRow row = *(this->get_selection()->get_selected());
row[col_type] = (type.empty() ? "<all>" : type);
row[col_type] = (type.empty() ? "<"s + C_("types", "all") + ">" : type);
row[col_type_real] = type;
}
}
@@ -233,9 +236,9 @@ GscPreferencesWindow::GscPreferencesWindow(BaseObjectType* gtkcobj, Glib::RefPtr
APP_BUILDER_AUTO_CONNECT(window_reset_all_button, clicked);
Glib::ustring smartctl_binary_tooltip = "A path to smartctl binary. If the path is not absolute, the binary will be looked for in user's PATH.";
Glib::ustring smartctl_binary_tooltip = _("A path to smartctl binary. If the path is not absolute, the binary will be looked for in user's PATH.");
#if defined CONFIG_KERNEL_FAMILY_WINDOWS
smartctl_binary_tooltip += Glib::ustring("\n") + "Note: smartctl.exe shows a console during execution, while smartctl-nc.exe (default) doesn't (nc means no-console).";
smartctl_binary_tooltip += Glib::ustring("\n") + _("Note: smartctl.exe shows a console during execution, while smartctl-nc.exe (default) doesn't (nc means no-console).");
#endif
if (auto* smartctl_binary_label = lookup_widget<Gtk::Label*>("smartctl_binary_label")) {
app_gtkmm_set_widget_tooltip(*smartctl_binary_label, smartctl_binary_tooltip);
@@ -258,11 +261,11 @@ GscPreferencesWindow::GscPreferencesWindow(BaseObjectType* gtkcobj, Glib::RefPtr
Gtk::Entry* device_options_device_entry = nullptr;
APP_BUILDER_AUTO_CONNECT(device_options_device_entry, changed);
Glib::ustring device_options_tooltip = "A device name to match";
Glib::ustring device_options_tooltip = _("A device name to match");
#if defined CONFIG_KERNEL_FAMILY_WINDOWS
device_options_tooltip = "A device name to match (for example, use \"pd0\" for the first physical drive)";
device_options_tooltip = _("A device name to match (for example, use \"pd0\" for the first physical drive)");
#elif defined CONFIG_KERNEL_LINUX
device_options_tooltip = "A device name to match (for example, /dev/sda or /dev/twa0)";
device_options_tooltip = _("A device name to match (for example, /dev/sda or /dev/twa0)");
#endif
if (auto* device_options_device_label = lookup_widget<Gtk::Label*>("device_options_device_label")) {
app_gtkmm_set_widget_tooltip(*device_options_device_label, device_options_tooltip);
@@ -475,9 +478,9 @@ void GscPreferencesWindow::on_window_ok_button_clicked()
if (contains_empty) {
Gtk::MessageDialog dialog(*this,
"You have specified an empty Parameters field for one or more entries"
_("You have specified an empty Parameters field for one or more entries"
" in Per-Drive Smartctl Parameters section. Such entries will be discarded.\n"
"\nDo you want to continue?",
"\nDo you want to continue?"),
true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true);
if (dialog.run() != Gtk::RESPONSE_YES) {
return;
@@ -498,7 +501,7 @@ void GscPreferencesWindow::on_window_ok_button_clicked()
void GscPreferencesWindow::on_window_reset_all_button_clicked()
{
Gtk::MessageDialog dialog(*this,
"\nAre you sure you want to reset all program settings to their defaults?\n",
"\n"s + _("Are you sure you want to reset all program settings to their defaults?") + "\n",
true, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true);
if (dialog.run() == Gtk::RESPONSE_YES) {
@@ -520,17 +523,17 @@ void GscPreferencesWindow::on_smartctl_binary_browse_button_clicked()
#ifdef _WIN32
Glib::RefPtr<Gtk::FileFilter> specific_filter = Gtk::FileFilter::create();
specific_filter->set_name("Executable Files");
specific_filter->set_name(_("Executable Files"));
specific_filter->add_pattern("*.exe");
Glib::RefPtr<Gtk::FileFilter> all_filter = Gtk::FileFilter::create();
all_filter->set_name("All Files");
all_filter->set_name(_("All Files"));
all_filter->add_pattern("*");
#endif
#if GTK_CHECK_VERSION(3, 20, 0)
hz::scoped_ptr<GtkFileChooserNative> dialog(gtk_file_chooser_native_new(
"Choose Smartctl Binary...", this->gobj(), GTK_FILE_CHOOSER_ACTION_OPEN, nullptr, nullptr), g_object_unref);
_("Choose Smartctl Binary..."), this->gobj(), GTK_FILE_CHOOSER_ACTION_OPEN, nullptr, nullptr), g_object_unref);
if (path.is_absolute())
gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog.get()), path.u8string().c_str());
@@ -543,7 +546,7 @@ void GscPreferencesWindow::on_smartctl_binary_browse_button_clicked()
result = gtk_native_dialog_run(GTK_NATIVE_DIALOG(dialog.get()));
#else
Gtk::FileChooserDialog dialog(*this, "Choose Smartctl Binary...",
Gtk::FileChooserDialog dialog(*this, _("Choose Smartctl Binary..."),
Gtk::FILE_CHOOSER_ACTION_OPEN);
// Add response buttons the the dialog
+6 -5
View File
@@ -13,6 +13,7 @@
#define GSC_TEXT_WINDOW_H
#include <gtkmm.h>
#include <glibmm/i18n.h>
#include <gdk/gdk.h> // GDK_KEY_Escape
#include "hz/debug.h"
@@ -140,16 +141,16 @@ class GscTextWindow : public AppBuilderWidget<GscTextWindow<InstanceSwitch>, Ins
int result = 0;
Glib::RefPtr<Gtk::FileFilter> specific_filter = Gtk::FileFilter::create();
specific_filter->set_name("Text Files");
specific_filter->set_name(_("Text Files"));
specific_filter->add_pattern("*.txt");
Glib::RefPtr<Gtk::FileFilter> all_filter = Gtk::FileFilter::create();
all_filter->set_name("All Files");
all_filter->set_name(_("All Files"));
all_filter->add_pattern("*");
#if GTK_CHECK_VERSION(3, 20, 0)
hz::scoped_ptr<GtkFileChooserNative> dialog(gtk_file_chooser_native_new(
"Save Data As...", this->gobj(), GTK_FILE_CHOOSER_ACTION_SAVE, nullptr, nullptr), g_object_unref);
_("Save Data As..."), this->gobj(), GTK_FILE_CHOOSER_ACTION_SAVE, nullptr, nullptr), g_object_unref);
gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog.get()), true);
@@ -165,7 +166,7 @@ class GscTextWindow : public AppBuilderWidget<GscTextWindow<InstanceSwitch>, Ins
result = gtk_native_dialog_run(GTK_NATIVE_DIALOG(dialog.get()));
#else
Gtk::FileChooserDialog dialog(*this, "Save Data As...",
Gtk::FileChooserDialog dialog(*this, _("Save Data As..."),
Gtk::FILE_CHOOSER_ACTION_SAVE);
// Add response buttons the the dialog
@@ -207,7 +208,7 @@ class GscTextWindow : public AppBuilderWidget<GscTextWindow<InstanceSwitch>, Ins
auto ec = hz::fs_file_put_contents(hz::fs::u8path(file), this->contents_.c_str());
if (ec) {
gui_show_error_dialog("Cannot save data to file", ec.message(), this);
gui_show_error_dialog(_("Cannot save data to file"), ec.message(), this);
}
break;
}
-22
View File
@@ -551,28 +551,6 @@ inline std::string fs_filename_make_safe(const std::string_view& filename)
/// Change the supplied path so that it's safe to create it
/// (remove any potentially harmful characters from it).
inline std::string fs_path_make_safe(const std::string_view& path)
{
std::string s(path);
std::string::size_type pos = 0;
while ((pos = s.find_first_not_of(
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890._-",
pos)) != std::string::npos) {
if (s[pos] != fs_preferred_separator)
s[pos] = '_';
++pos;
}
// win32 kernel (heh) has trouble with space and dot-ending files
if (!s.empty() && (s[s.size() - 1] == '.' || s[s.size() - 1] == ' ')) {
s[s.size() - 1] = '_';
}
return s;
}
} // ns hz
+5
View File
@@ -29,9 +29,14 @@ namespace hz {
#ifdef __cpp_lib_filesystem
namespace fs = std::filesystem;
#else // __cpp_lib_experimental_filesystem
// Note: This requires -lstdc++fs with gcc's libstdc++, -lc++experimental with clang's libc++.
namespace fs = std::experimental::filesystem;
#endif
+1 -1
View File
@@ -3,5 +3,5 @@ METASOURCES = AUTO
noinst_HEADERS = json.hpp
noinst_DATA = LICENSE.MIT json_version.txt
noinst_DATA = json_version.txt
-500
View File
@@ -1,500 +0,0 @@
# Makefile.in generated by automake 1.13.4 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
subdir = src/json
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(noinst_HEADERS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = \
$(top_srcdir)/autoconf.m4/app_auto_clear_flags.m4 \
$(top_srcdir)/autoconf.m4/app_compiler_options.m4 \
$(top_srcdir)/autoconf.m4/app_detect_os.m4 \
$(top_srcdir)/autoconf.m4/app_get_mt_flags.m4 \
$(top_srcdir)/autoconf.m4/ax_compiler_vendor.m4 \
$(top_srcdir)/autoconf.m4/ax_cxx_compile_stdcxx.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
SOURCES =
DIST_SOURCES =
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
DATA = $(noinst_DATA)
HEADERS = $(noinst_HEADERS)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTODIRS = @AUTODIRS@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EXEEXT = @EXEEXT@
GTKMM_CFLAGS = @GTKMM_CFLAGS@
GTKMM_LIBS = @GTKMM_LIBS@
HAVE_CXX17 = @HAVE_CXX17@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NSIS_EXEC = @NSIS_EXEC@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PCRECPP_CFLAGS = @PCRECPP_CFLAGS@
PCRECPP_LIBS = @PCRECPP_LIBS@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
RANLIB = @RANLIB@
RES_DIST = @RES_DIST@
RES_LIBADD = @RES_LIBADD@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
WINDOWS_ARCH = @WINDOWS_ARCH@
WINDOWS_SUFFIX = @WINDOWS_SUFFIX@
WINDOWS_SYSROOT = @WINDOWS_SYSROOT@
WINDRES = @WINDRES@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pcre_config_binary = @pcre_config_binary@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
AM_CPPFLAGS = $(all_includes)
METASOURCES = AUTO
noinst_HEADERS = json.hpp
noinst_DATA = LICENSE.MIT json_version.txt
all: all-am
.SUFFIXES:
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/json/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign src/json/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(DATA) $(HEADERS)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic mostlyclean-am
distclean: distclean-am
-rm -f Makefile
distclean-am: clean-am distclean-generic distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am:
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
cscopelist-am ctags ctags-am distclean distclean-generic \
distclean-tags distdir dvi dvi-am html html-am info info-am \
install install-am install-data install-data-am install-dvi \
install-dvi-am install-exec install-exec-am install-html \
install-html-am install-info install-info-am install-man \
install-pdf install-pdf-am install-ps install-ps-am \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
@@ -65,12 +65,11 @@ namespace {
/// Main function for the test
int main(int argc, char *argv[])
{
debug_register_domain("dom");
debug_set_enabled("dom", debug_level::dump, false);
debug_set_format("dom", debug_level::info,
(!debug_get_formats("dom")[debug_level::info].none() & ~debug_format::color) | debug_format::datetime);
(debug_get_formats("dom")[debug_level::info].to_ulong() & ~debug_format::color) | debug_format::datetime);
std::string something = "some thing";
+29 -8
View File
@@ -1,23 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<!-- Generated with glade 3.20.0
Copyright (C) Alexander Shaduri
This file is part of GSmartControl.
GSmartControl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GSmartControl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GSmartControl. If not, see <http://www.gnu.org/licenses/>.
-->
<interface>
<requires lib="gtk+" version="3.4"/>
<requires lib="gtk+" version="3.20"/>
<!-- interface-license-type gplv3 -->
<!-- interface-name GSmartControl -->
<!-- interface-copyright Alexander Shaduri -->
<object class="GtkAboutDialog" id="gsc_about_dialog">
<property name="can_focus">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="border_width">6</property>
<property name="title" translatable="yes">About GSmartControl</property>
<property name="resizable">False</property>
<property name="window_position">center-on-parent</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">dialog</property>
<property name="copyright" translatable="yes">here be copyrights</property>
<property name="comments" translatable="yes">Control and monitor hard disk SMART data</property>
<property name="license" translatable="yes">here be license</property>
<property name="authors">here be authors</property>
<property name="copyright">[here be copyrights]</property>
<property name="comments" translatable="yes">Hard disk drive and SSD health inspection tool</property>
<property name="authors">[here be authors]</property>
<property name="documenters">here be documentors</property>
<property name="translator_credits" translatable="yes">translator-credits</property>
<property name="translator_credits">translator-credits</property>
<property name="logo_icon_name"/>
<property name="license_type">gpl-3-0-only</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
<property name="visible">True</property>
@@ -1,7 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<!-- Generated with glade 3.20.0
Copyright (C) Alexander Shaduri
This file is part of GSmartControl.
GSmartControl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GSmartControl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GSmartControl. If not, see <http://www.gnu.org/licenses/>.
-->
<interface>
<requires lib="gtk+" version="3.4"/>
<requires lib="gtk+" version="3.20"/>
<!-- interface-license-type gplv3 -->
<!-- interface-name GSmartControl -->
<!-- interface-copyright Alexander Shaduri -->
<object class="GtkWindow" id="gsc_add_device_window">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Add Device - GSmartControl</property>
@@ -19,12 +41,12 @@
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel" id="label1">
<object class="GtkLabel" id="top_info_link_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">The Smartctl Options section in the All Help Topics
menu contains information on what you can enter here.</property>
<property name="label" translatable="yes">The &lt;a href="%1"&gt;smartctl man page&lt;/a&gt; contains information on what you can enter here.</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="expand">True</property>
@@ -61,7 +83,7 @@ menu contains information on what you can enter here.</property>
</child>
<child>
<object class="GtkButton" id="device_name_browse_button">
<property name="label" translatable="yes">_Browse...</property>
<property name="label" translatable="yes">Browse...</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
@@ -84,7 +106,7 @@ menu contains information on what you can enter here.</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Device _type:</property>
<property name="label" translatable="yes">Device type:</property>
<property name="use_underline">True</property>
</object>
<packing>
@@ -141,7 +163,7 @@ menu contains information on what you can enter here.</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Device _name:</property>
<property name="label" translatable="yes">Device name:</property>
<property name="use_underline">True</property>
</object>
<packing>
@@ -162,8 +184,8 @@ menu contains information on what you can enter here.</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Note: To permanently add a device, you'll have to use
the gsmartcontrol --add-device command line option.</property>
<property name="label" translatable="yes">Note: To make this change permanent, you'll have to add the gsmartcontrol --add-device command line option to its shortcut.</property>
<property name="wrap">True</property>
</object>
<packing>
<property name="expand">True</property>
@@ -1,7 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<!-- Generated with glade 3.20.0
Copyright (C) Alexander Shaduri
This file is part of GSmartControl.
GSmartControl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GSmartControl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GSmartControl. If not, see <http://www.gnu.org/licenses/>.
-->
<interface>
<requires lib="gtk+" version="3.4"/>
<requires lib="gtk+" version="3.20"/>
<!-- interface-license-type gplv3 -->
<!-- interface-name GSmartControl -->
<!-- interface-copyright Alexander Shaduri -->
<object class="GtkWindow" id="gsc_executor_log_window">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Execution Log - GSmartControl</property>
+36 -10
View File
@@ -1,7 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<!-- Generated with glade 3.20.0
Copyright (C) Alexander Shaduri
This file is part of GSmartControl.
GSmartControl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GSmartControl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GSmartControl. If not, see <http://www.gnu.org/licenses/>.
-->
<interface>
<requires lib="gtk+" version="3.4"/>
<requires lib="gtk+" version="3.20"/>
<!-- interface-license-type gplv3 -->
<!-- interface-name GSmartControl -->
<!-- interface-copyright Alexander Shaduri -->
<object class="GtkListStore" id="model1">
<columns>
<!-- column-name gchararray -->
@@ -310,7 +332,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Self-tests are built-in tests within the drive designed to recognize drive fault conditions. All self-tests are safe to user data. The tests can be performed during normal system operation, but will take longer to complete if the drive is not idle. You will not be able to access the drive's SMART data while a test is in progress.</property>
<property name="label" translatable="yes">Self-tests are built-in tests within the drive designed to recognize drive fault conditions. All self-tests are safe to user data. The tests can be performed during normal system operation, but will take longer to complete if the drive is not idle.</property>
<property name="wrap">True</property>
<property name="width_chars">70</property>
</object>
@@ -347,7 +369,7 @@
<object class="GtkLabel" id="test_result_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Test result text</property>
<property name="label">[Test result text placeholder]</property>
<property name="use_markup">True</property>
<property name="width_chars">70</property>
</object>
@@ -370,7 +392,7 @@
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Test progress</property>
<property name="hexpand">True</property>
<property name="text" translatable="yes">Test completion: 90%; ETA: 12 minutes</property>
<property name="text">[test completion % and ETA placeholder text]</property>
<property name="show_text">True</property>
<property name="ellipsize">end</property>
</object>
@@ -449,8 +471,10 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">&lt;b&gt;Test type:&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="label" translatable="yes">Test type:</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
@@ -488,8 +512,10 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Estimated test duration on idle drive</property>
<property name="label" translatable="yes">&lt;b&gt;Estimated duration:&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="label" translatable="yes">Estimated duration:</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
@@ -1055,8 +1081,8 @@ Self-test log contains information about the most recent manually performed SMAR
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Re-read all the information</property>
<property name="use_stock">True</property>
<accelerator key="F5" signal="clicked"/>
<accelerator key="R" signal="clicked" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="F5" signal="clicked"/>
</object>
<packing>
<property name="expand">True</property>
+38 -10
View File
@@ -1,7 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<!-- Generated with glade 3.20.0
Copyright (C) Alexander Shaduri
This file is part of GSmartControl.
GSmartControl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GSmartControl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GSmartControl. If not, see <http://www.gnu.org/licenses/>.
-->
<interface>
<requires lib="gtk+" version="3.4"/>
<requires lib="gtk+" version="3.20"/>
<!-- interface-license-type gplv3 -->
<!-- interface-name GSmartControl -->
<!-- interface-copyright Alexander Shaduri -->
<object class="GtkWindow" id="gsc_main_window">
<property name="can_focus">False</property>
<property name="title" translatable="yes">GSmartControl</property>
@@ -67,8 +89,10 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">&lt;b&gt;Drive information:&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="label" translatable="yes">Drive information:</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="left_attach">0</property>
@@ -80,8 +104,10 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">&lt;b&gt;Basic health check:&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="label" translatable="yes">Basic health check:</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="left_attach">0</property>
@@ -93,9 +119,11 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">&lt;b&gt;Model family:&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="label" translatable="yes">Model family:</property>
<property name="selectable">True</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="left_attach">0</property>
@@ -161,7 +189,7 @@
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="status_smart_enabled_check">
<property name="label" translatable="yes">enable smart (action-replaced text)</property>
<property name="label">enable smart (action-replaced text)</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
@@ -175,7 +203,7 @@
</child>
<child>
<object class="GtkCheckButton" id="status_aodc_enabled_check">
<property name="label" translatable="yes">enable aodc (action-replaced text)</property>
<property name="label">enable aodc (action-replaced text)</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
@@ -1,7 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<!-- Generated with glade 3.20.0
Copyright (C) Alexander Shaduri
This file is part of GSmartControl.
GSmartControl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GSmartControl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GSmartControl. If not, see <http://www.gnu.org/licenses/>.
-->
<interface>
<requires lib="gtk+" version="3.4"/>
<requires lib="gtk+" version="3.20"/>
<!-- interface-license-type gplv3 -->
<!-- interface-name GSmartControl -->
<!-- interface-copyright Alexander Shaduri -->
<object class="GtkWindow" id="gsc_preferences_window">
<property name="can_focus">False</property>
<child>
@@ -52,10 +74,11 @@
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="scan_on_startup_check">
<property name="label" translatable="yes">_Scan system for drives on startup</property>
<property name="label" translatable="yes">Scan system for drives on startup</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">start</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
@@ -71,6 +94,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">start</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
@@ -86,6 +110,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">start</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
@@ -101,6 +126,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">start</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
@@ -162,11 +188,12 @@
<property name="spacing">7</property>
<child>
<object class="GtkCheckButton" id="search_in_smartmontools_first_check">
<property name="label" translatable="yes">Loo_k for smartctl in smartmontools installation directory first</property>
<property name="label" translatable="yes">Look for smartctl in smartmontools installation directory first</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">If smartmontools is installed, use its smartctl by default</property>
<property name="halign">start</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
@@ -203,7 +230,7 @@
</child>
<child>
<object class="GtkButton" id="smartctl_binary_browse_button">
<property name="label" translatable="yes">_Browse...</property>
<property name="label" translatable="yes">Browse...</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
@@ -254,7 +281,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">S_martctl binary:</property>
<property name="label" translatable="yes">Smartctl binary:</property>
<property name="use_underline">True</property>
</object>
<packing>
@@ -387,8 +414,10 @@
<object class="GtkLabel" id="label10">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Drive Search&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="label" translatable="yes">Drive Search</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
</object>
@@ -537,7 +566,7 @@
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Smartctl parameters to add (for example, "-T permissive" or "-d usbsunplus")</property>
<property name="halign">start</property>
<property name="label" translatable="yes">_Parameters:</property>
<property name="label" translatable="yes">Parameters:</property>
<property name="use_underline">True</property>
</object>
<packing>
@@ -551,7 +580,7 @@
<property name="can_focus">False</property>
<property name="tooltip_text" translatable="yes">Match only this type of device (as used by the -d smartctl parameter). Leave empty for all types. This can be used to match a drive behind a RAID device, e.g. "areca,2".</property>
<property name="halign">start</property>
<property name="label" translatable="yes">_Type:</property>
<property name="label" translatable="yes">Type:</property>
<property name="use_underline">True</property>
</object>
<packing>
@@ -564,7 +593,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">De_vice:</property>
<property name="label" translatable="yes">Device:</property>
<property name="use_underline">True</property>
</object>
<packing>
@@ -615,8 +644,10 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">&lt;b&gt;Drive Properties:&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="label" translatable="yes">Drive Properties:</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="left_attach">0</property>
@@ -654,8 +685,10 @@
<object class="GtkLabel" id="label11">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">&lt;b&gt;Per-drive Smartctl Parameters&lt;/b&gt;</property>
<property name="use_markup">True</property>
<property name="label" translatable="yes">Per-drive Smartctl Parameters</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
</child>
</object>
@@ -709,7 +742,7 @@
<property name="homogeneous">True</property>
<child>
<object class="GtkButton" id="window_reset_all_button">
<property name="label" translatable="yes">Reset a_ll</property>
<property name="label" translatable="yes">_Reset all</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
+24 -2
View File
@@ -1,7 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.20.0 -->
<!-- Generated with glade 3.20.0
Copyright (C) Alexander Shaduri
This file is part of GSmartControl.
GSmartControl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
GSmartControl is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GSmartControl. If not, see <http://www.gnu.org/licenses/>.
-->
<interface>
<requires lib="gtk+" version="3.4"/>
<requires lib="gtk+" version="3.20"/>
<!-- interface-license-type gplv3 -->
<!-- interface-name GSmartControl -->
<!-- interface-copyright Alexander Shaduri -->
<object class="GtkWindow" id="gsc_text_window">
<property name="can_focus">False</property>
<property name="title" translatable="yes">GSmartControl</property>