diff --git a/.gitignore b/.gitignore index 2a19419..c79c629 100644 --- a/.gitignore +++ b/.gitignore @@ -39,7 +39,6 @@ Makefile.in # CMake CMakeCache.txt CMakeFiles -CMakeLists.txt Makefile cmake_install.cmake install_manifest.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..26ac66b --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,59 @@ +# CMakeLists.txt for libyui-mga-gtk +# +# Usage: +# +# mkdir build +# cd build +# cmake .. +# +# make +# sudo make install +# +# Restart with a clean build environment: +# rm -rf build +# +# Show the complete compiler commands with all arguments: +# make VERBOSE=1 + +cmake_minimum_required( VERSION 3.17 ) +project( libyui-mga-gtk ) + +# Options usage: +# +# cmake -DBUILD_DOC=on -DBUILD_EXAMPLES=off .. + +option( BUILD_SRC "Build in src/ subdirectory" on ) +option( BUILD_DOC "Build class documentation" off ) +option( WERROR "Treat all compiler warnings as errors" off ) + +# Non-boolean options +set( DOC_DESTDIR "" CACHE STRING "Destination directory prefix for installing docs" ) + +#---------------------------------------------------------------------- + + +set( CMAKE_INSTALL_MESSAGE LAZY ) # Suppress "up-to-date" messages during "make install" + +add_compile_options( "-Wall" ) +IF (NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + # Initialize compiler flags for all targets in all subdirectories + add_compile_options( "-Os" ) # Optimize for size (overrides CMake's -O3 in RELEASE builds) +endif() + +if ( WERROR ) + add_compile_options( "-Werror" ) +endif() + + +# +# Descend into subdirectories +# + +if ( BUILD_SRC ) + add_subdirectory( src ) +endif() + +# TODO +#if ( BUILD_DOC ) +# add_subdirectory( doc ) +#endif() diff --git a/VERSION.cmake b/VERSION.cmake index edb4046..d3888e9 100644 --- a/VERSION.cmake +++ b/VERSION.cmake @@ -1,6 +1,7 @@ SET(VERSION_MAJOR "1") SET(VERSION_MINOR "1") SET(VERSION_PATCH "0") + SET( VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}${GIT_SHA1_VERSION}" ) ##### This is need for the libyui core, ONLY. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9318ee5..4b2b48f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,2 +1,120 @@ -PROCESS_SOURCES() +# CMakeLists.txt for libyui-qt/src +include( ../VERSION.cmake ) +include( GNUInstallDirs ) # set CMAKE_INSTALL_INCLUDEDIR, ..._LIBDIR + +# Use the package PkgConfig to detect GTK+ headers/library files +FIND_PACKAGE(PkgConfig REQUIRED) +PKG_CHECK_MODULES(GTK3 REQUIRED gtk+-3.0) + +PKG_CHECK_MODULES(YUI REQUIRED libyui) +pkg_get_variable(YUI_SO_VERSION libyui soversion) +pkg_get_variable(YUI_SO_MAJOR libyui soversion_major) +#pkg_get_variable(YUI_SO_MINOR libyui soversion_minor) +#pkg_get_variable(YUI_SO_PATCH libyui soversion_patch) + +message (STATUS "Using ${YUI_LIBRARY_DIRS}/libyui.so.${YUI_SO_VERSION}") +find_package(Boost COMPONENTS system filesystem REQUIRED) + +##### This is needed to be set for the libyui core +SET( SONAME_MAJOR ${YUI_SO_MAJOR} ) +SET( SONAME ${YUI_SO_VERSION} ) + +PKG_CHECK_MODULES(YUIMGA REQUIRED libyui-mga) + +# +# libyui plugin specific +# + +set( TARGETLIB libyui-mga-gtk ) +set( TARGETLIB_BASE yui-mga-gtk ) + +set( HEADERS_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}/yui/mga/gtk ) +set( PLUGIN_DIR ${CMAKE_INSTALL_LIBDIR}/yui ) # /usr/lib64/yui + +# if DESTDIR is set, CMAKE_INSTALL_INCLUDEDIR already contains it +# during "make install" (but not for other make targets!): +# +# sudo make install DESTDIR=/work/foo +# or +# DESTDIR=/work/foo sudo make install +# +# -> the include files are installed to /work/foo/usr/include/... +# We need that for RPM builds to install everything to $RPM_BUILD_ROOT. + + +set( SOURCES + YGWE.cc + YMGAGMenuBar.cc + YMGA_GCBTable.cc + YMGAGWidgetFactory.cc + ) + + +set( HEADERS + YGWE.h + YMGAGMenuBar.h + YMGA_GCBTable.h + YMGAGWidgetFactory.h + ) + + +# Add shared lib to be built +add_library( ${TARGETLIB} SHARED + ${SOURCES} + ${HEADERS} + ) + + +# Include directories and compile options +# + +# Setup CMake to use GTK+, tell the compiler where to look for headers +# and to the linker where to look for libraries +INCLUDE_DIRECTORIES(${GTK3_INCLUDE_DIRS} ${YUI_INCLUDE_DIRS} ${YUIMGA_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}) + + +# Make the version from ../../VERSION.cmake available as a #define +target_compile_definitions( ${TARGETLIB} PUBLIC VERSION="${VERSION}" ) + + +# +# Linking +# + +# https://cmake.org/cmake/help/latest/command/link_directories.html suggests to use target_link_libraries +# and anyway LINK_DIRECTORIES command will apply only to targets created after it is called, so must be set +# before add_library in the case. +target_link_directories( ${TARGETLIB} + PUBLIC ${YUI_LIBRARY_DIRS} + PUBLIC ${YUIMGA_LIBRARY_DIRS} + PUBLIC ${GTK3_LIBRARY_DIRS} +) + + +# Libraries that are needed to build this shared lib +# +# If in doubt what is really needed, check with "ldd -u" which libs are unused. +target_link_libraries( ${TARGETLIB} + ${YUI_LIBRARIES} + ${YUIMGA_LIBRARIES} + ${GTK3_LIBRARIES} + ${Boost_FILESYSTEM_LIBRARY} + ) + + +# https://cmake.org/cmake/help/latest/manual/cmake-properties.7.html#target-properties +set_target_properties( ${TARGETLIB} PROPERTIES + VERSION ${SONAME} # From ../../VERSION.cmake + SOVERSION ${SONAME_MAJOR} # From ../../VERSION.cmake + OUTPUT_NAME ${TARGETLIB_BASE} + ) + + +# +# Install +# + +# Install the headers first so the message about the lib does not scroll away +install( FILES ${HEADERS} DESTINATION ${HEADERS_INSTALL_DIR} ) +install( TARGETS ${TARGETLIB} LIBRARY DESTINATION ${PLUGIN_DIR} ) diff --git a/src/YMGAGMenuBar.cc b/src/YMGAGMenuBar.cc index 503f1be..18855ab 100644 --- a/src/YMGAGMenuBar.cc +++ b/src/YMGAGMenuBar.cc @@ -22,13 +22,13 @@ Author: Angelo Naselli /-*/ +#define YUILogComponent "mga-gtk-ui" +#include #include -#define YUILogComponent "mga-gtk-ui" -#include -#include +// #include #include #include #include diff --git a/src/YMGAGWidgetFactory.cc b/src/YMGAGWidgetFactory.cc index adc5d24..38486a9 100644 --- a/src/YMGAGWidgetFactory.cc +++ b/src/YMGAGWidgetFactory.cc @@ -27,7 +27,7 @@ #include #include "YMGAGWidgetFactory.h" -#include +// #include #include #include @@ -52,9 +52,11 @@ YMGAGWidgetFactory::~YMGAGWidgetFactory() } -YMGA_CBTable * YMGAGWidgetFactory::createCBTable( YWidget * parent, YTableHeader * header, YCBTableMode mode ) +YMGA_CBTable * YMGAGWidgetFactory::createCBTable( YWidget * parent, YTableHeader * header) { - YMGA_GCBTable * table = new YMGA_GCBTable( parent, header, mode ); + YCBTableHeader *hdr = dynamic_cast(header); + YUI_CHECK_NEW(hdr); + YMGA_GCBTable * table = new YMGA_GCBTable( parent, hdr ); YUI_CHECK_NEW( table ); return table; diff --git a/src/YMGAGWidgetFactory.h b/src/YMGAGWidgetFactory.h index f4a7199..a4ef631 100644 --- a/src/YMGAGWidgetFactory.h +++ b/src/YMGAGWidgetFactory.h @@ -27,9 +27,10 @@ #define YMGAGWidgetFactory_h +#include #include -#include "YMGA_CBTable.h" +// #include "YMGA_CBTable.h" using std::string; @@ -42,7 +43,7 @@ class YMGAGWidgetFactory: public YMGAWidgetFactory { public: - virtual YMGA_CBTable * createCBTable ( YWidget * parent, YTableHeader * header_disown, YCBTableMode mode = YCBTableCheckBoxOnFirstColumn ); + virtual YMGA_CBTable * createCBTable ( YWidget * parent, YTableHeader * header_disown ); virtual YMGAMenuBar * createMenuBar ( YWidget *parent ); protected: diff --git a/src/YMGA_GCBTable.cc b/src/YMGA_GCBTable.cc index ccd5839..80f7819 100644 --- a/src/YMGA_GCBTable.cc +++ b/src/YMGA_GCBTable.cc @@ -25,9 +25,8 @@ #include -#define YUILogComponent "mga-gtk-ui" -#include + #include #include #include @@ -41,6 +40,12 @@ #include #include +#ifdef YUILogComponent +#undef YUILogComponent +#endif +#define YUILogComponent "mga-gtk-ui" +#include + #include "YMGA_GCBTable.h" //**** YMGA_GTreeView implementation @@ -269,15 +274,19 @@ void YMGA_GTreeView::toggleMark (GtkTreePath *path, gint column) YMGA_CBTable * pTable = dynamic_cast(this); if (pTable) { - if ( (pTable->tableMode() == YCBTableMode::YCBTableCheckBoxOnFirstColumn && column == 0) - || - (pTable->tableMode() == YCBTableMode::YCBTableCheckBoxOnLastColumn && column == (pTable->columns()-1)*3 )) - { - setRowMark (&iter, column, state); - pYCBTableItem->check(state); - pTable->setChangedItem(pYCBTableItem); - emitEvent (YEvent::ValueChanged); - } + int col = column / 3; + if (pTable->isCheckBoxColumn(col)) + { + setRowMark (&iter, column, state); + // checkboxItemColumn is true so hasCell is as well and column exists + YCBTableCell *cell = dynamic_cast(pYCBTableItem->cell(col)); + YUI_CHECK_PTR( cell ); + cell->setChecked( state == TRUE ); + pYCBTableItem->setChangedColumn(col); + pTable->setChangedItem ( pYCBTableItem ); + + emitEvent (YEvent::ValueChanged); + } } } else @@ -403,24 +412,21 @@ void YMGA_GTreeView::right_click_cb (YGtkTreeView *view, gboolean outreach, YMGA //**** YMGA_GCBTable implementation -YMGA_GCBTable::YMGA_GCBTable (YWidget *parent, YTableHeader *headers, YCBTableMode mode) - : YMGA_CBTable (NULL, headers, mode), +YMGA_GCBTable::YMGA_GCBTable (YWidget *parent, YCBTableHeader *headers) + : YMGA_CBTable (NULL, headers), YMGA_GTreeView (this, parent, std::string(), false) { gtk_tree_view_set_headers_visible (getView(), TRUE); ygtk_tree_view_set_empty_text (YGTK_TREE_VIEW (getView()), _("No entries.")); int columnNumber = columns(); - yuiMilestone() << " Slection mode " << mode << std::endl; - GType types [columnNumber*3]; for (int i = 0; i < columnNumber; i++) { int t = i*3; types[t+0] = G_TYPE_BOOLEAN; types[t+1] = GDK_TYPE_PIXBUF; types[t+2] = G_TYPE_STRING; - if ( (i==0 && mode == YCBTableCheckBoxOnFirstColumn) || - (i == columnNumber-1 && mode == YCBTableCheckBoxOnLastColumn)) + if ( isCheckBoxColumn(i) ) addCheckColumn(header(i), t); else addTextColumn (header(i), alignment (i), t+1, t+2); @@ -446,7 +452,6 @@ void YMGA_GCBTable::setSortable (bool sortable) return; int n = 0; GList *columns = gtk_tree_view_get_columns (getView()); - int mode = tableMode(); int columnNumber = YMGA_GCBTable::columns(); for (GList *i = columns; i; i = i->next, n++) { GtkTreeViewColumn *column = (GtkTreeViewColumn *) i->data; @@ -455,8 +460,7 @@ void YMGA_GCBTable::setSortable (bool sortable) if (sortable) { // offset 2 is text (G_TYPE_STRING) int index = (n*3)+2; - if (! ( (n==0 && mode == YCBTableCheckBoxOnFirstColumn) || - (n == columnNumber-1 && mode == YCBTableCheckBoxOnLastColumn))) + if ( !isCheckBoxColumn(n) ) { gtk_tree_sortable_set_sort_func ( GTK_TREE_SORTABLE (getModel()), index, tree_sort_cb, @@ -502,8 +506,7 @@ void YMGA_GCBTable::cellChanged (const YTableCell *cell) { GtkTreeIter iter; getTreeIter (cell->parent(), &iter); - int mode = tableMode(); - int column = (mode == YCBTableCheckBoxOnLastColumn ? cell->column() : cell->column() +1); + int column = cell->column(); setCell (&iter, column, cell); } @@ -513,27 +516,19 @@ void YMGA_GCBTable::doAddItem (YItem *_item) if (item) { GtkTreeIter iter; addRow (item, &iter); - int i = 0; - if (tableMode() == YCBTableMode::YCBTableCheckBoxOnFirstColumn ) - { - setRowMark(&iter, i++, item->checked()); - } + for (YTableCellIterator it = item->cellsBegin(); it != item->cellsEnd(); it++) { - if (i >= columns()) - { - yuiWarning() << "Item contains too many columns, current is " << i - << " but only " << columns() << " columns are configured" << std::endl; - } - else - setCell (&iter, i++, *it); - } - if (tableMode() == YCBTableMode::YCBTableCheckBoxOnLastColumn ) - { - int col = columns() -1; - setRowMark(&iter, col*3, item->checked()); + YCBTableCell *cbCell = dynamic_cast(*it); + if ( cbCell && isCheckBoxColumn( cbCell->column() ) ) + { + setRowMark(&iter, cbCell->column()*3, cbCell->checked()); + } + else + setCell (&iter, (*it)->column(), *it); } + if (item->selected()) focusItem (item, true); } @@ -541,7 +536,7 @@ void YMGA_GCBTable::doAddItem (YItem *_item) yuiError() << "Can only add YCBTableItems to a YTable.\n"; } -void YMGA_GCBTable::checkItem ( YItem* item, bool checked ) +void YMGA_GCBTable::setItemChecked ( YItem* item, int column, bool checked ) { GtkTreeIter iter; YCBTableItem *pItem = dynamic_cast (item); @@ -549,7 +544,10 @@ void YMGA_GCBTable::checkItem ( YItem* item, bool checked ) getTreeIter ( item, &iter ); blockSelected(); setRowMark ( &iter, markColumn, checked ); - pItem->check(checked); + + YCBTableCell *cell = dynamic_cast(pItem->cell(column)); + YUI_CHECK_PTR( cell ); + cell->setChecked( checked ); } void YMGA_GCBTable::doSelectItem (YItem *item, bool select) diff --git a/src/YMGA_GCBTable.h b/src/YMGA_GCBTable.h index 2eb8c3e..386428c 100644 --- a/src/YMGA_GCBTable.h +++ b/src/YMGA_GCBTable.h @@ -122,7 +122,7 @@ class YMGA_GTreeView : public YGScrolledWidget, public YGSelectionStore class YMGA_GCBTable : public YMGA_CBTable, public YMGA_GTreeView { public: - YMGA_GCBTable (YWidget *parent, YTableHeader *headers, YCBTableMode mode); + YMGA_GCBTable (YWidget *parent, YCBTableHeader *headers ); void setSortable (bool sortable); @@ -143,7 +143,7 @@ class YMGA_GCBTable : public YMGA_CBTable, public YMGA_GTreeView void doDeselectAllItems(); - virtual void checkItem( YItem * item, bool checked = true ); + virtual void setItemChecked( YItem * item, int column, bool checked = true ); // callbacks static void activateButton (YWidget *button);