Browse Source

Conversion to the cmake building system.

Signed-off-by: gregory guy <gregory-tde@laposte.net>
Signed-off-by: Slávek Banko <slavek.banko@axis.cz>
pull/5/head
gregory guy 2 years ago committed by Slávek Banko
parent
commit
2578c13462
Signed by: SlavekB
GPG Key ID: 608F5293A04BE668
  1. 90
      CMakeLists.txt
  2. 119
      ConfigureChecks.cmake
  3. 6
      backgrounds-previews/CMakeLists.txt
  4. 6
      backgrounds/CMakeLists.txt
  5. 17
      config.h.cmake
  6. 14
      doc/CMakeLists.txt
  7. 1
      doc/en/CMakeLists.txt
  8. 5
      doc/man/CMakeLists.txt
  9. 171
      doc/man/basket.1
  10. 62
      file-integration/CMakeLists.txt
  11. 6
      images/CMakeLists.txt
  12. 72
      kontact_plugin/CMakeLists.txt
  13. 14
      po/CMakeLists.txt
  14. 138
      src/CMakeLists.txt
  15. 3
      tags/CMakeLists.txt
  16. 6
      welcome/CMakeLists.txt

90
CMakeLists.txt

@ -0,0 +1,90 @@
############################################
# #
# Improvements and feedbacks are welcome #
# #
# This file is released under GPL >= 3 #
# #
############################################
cmake_minimum_required( VERSION 2.8 )
#### general package setup
project( basket )
set( VERSION R14.1.0 )
#### include essential cmake modules
include( FindPkgConfig )
include( CheckFunctionExists )
include( CheckSymbolExists )
include( CheckIncludeFile )
include( CheckIncludeFileCXX )
include( CheckLibraryExists )
include( CheckCSourceCompiles )
include( CheckCXXSourceCompiles )
#### include our cmake modules
set( CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules" )
include( TDEMacros )
##### setup install paths
include( TDESetupPaths )
tde_setup_paths( )
##### optional stuff
option( WITH_ALL_OPTIONS "Enable all optional support" OFF )
option( WITH_GCC_VISIBILITY "Enable fvisibility and fvisibility-inlines-hidden" ${WITH_ALL_OPTIONS} )
option( WITH_GPGME "Enable libgpgme support" ${WITH_ALL_OPTIONS} )
option( WITH_LIBART "Enable Libart support" ${WITH_ALL_OPTIONS} )
option( WITH_ARTS "Enable aRts support" ${WITH_ALL_OPTIONS} )
##### user requested modules
option( BUILD_ALL "Build all" ON )
option( BUILD_KONTACT_PLUGIN "Build kontact_plugin " ${BUILD_ALL} )
option( BUILD_DOC "Build documentation" ${BUILD_ALL} )
option( BUILD_TRANSLATIONS "Build translations" ${BUILD_ALL} )
##### configure checks
include( ConfigureChecks.cmake )
###### global compiler settings
add_definitions( -DHAVE_CONFIG_H )
set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TQT_CXX_FLAGS}" )
set( CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined" )
set( CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined" )
##### directories
add_subdirectory( src )
add_subdirectory( tags )
add_subdirectory( images )
add_subdirectory( welcome )
add_subdirectory( backgrounds )
add_subdirectory( file-integration )
add_subdirectory( backgrounds-previews )
tde_conditional_add_subdirectory( BUILD_KONTACT_PLUGIN kontact_plugin )
tde_conditional_add_subdirectory( BUILD_DOC doc )
tde_conditional_add_subdirectory( BUILD_TRANSLATIONS po )
##### write configure files
configure_file( config.h.cmake config.h @ONLY )

119
ConfigureChecks.cmake

@ -0,0 +1,119 @@
############################################
# #
# Improvements and feedbacks are welcome #
# #
# This file is released under GPL >= 3 #
# #
############################################
# required stuff
find_package( TQt )
find_package( TDE )
tde_setup_architecture_flags( )
include(TestBigEndian)
test_big_endian(WORDS_BIGENDIAN)
tde_setup_largefiles( )
##### check for gcc visibility support
if( WITH_GCC_VISIBILITY )
tde_setup_gcc_visibility( )
endif( WITH_GCC_VISIBILITY )
##### check for the file program
find_program( FILE_EXECUTABLE file )
if( NOT FILE_EXECUTABLE )
tde_message_fatal( "the program 'file' is required to build basket, but was not found on your system" )
endif()
##### check for X11
find_package( X11 )
##### check for gpgme
if( WITH_GPGME )
pkg_search_module( GPGME gpgme )
if( NOT GPGME_FOUND )
find_program( GPGME_CONFIG_EXECUTABLE gpgme-config )
if( NOT GPGME_CONFIG_EXECUTABLE )
tde_message_fatal( "Gpgme library is required but not found on your system" )
endif()
execute_process(
COMMAND ${GPGME_CONFIG_EXECUTABLE} --libs
OUTPUT_VARIABLE GPGME_LIBRARIES
ERROR_VARIABLE GPGME_LIBRARIES
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND ${GPGME_CONFIG_EXECUTABLE} --cflags
OUTPUT_VARIABLE GPGME_CFLAGS
ERROR_VARIABLE GPGME_CFLAGS
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_STRIP_TRAILING_WHITESPACE
)
string( REGEX MATCHALL "-I([^ ]*)" GPGME_INCLUDE_FLAGS "${GPGME_CFLAGS}" )
string( REGEX REPLACE "-I" "" GPGME_INCLUDE_DIRS "${GPGME_INCLUDE_FLAGS}" )
set( GPGME_INCLUDE_DIRS "${GPGME_INCLUDE_DIRS}" CACHE INTERNAL "" )
set( GPGME_LIBRARIES "${GPGME_LIBRARIES}" CACHE INTERNAL "" )
set( HAVE_LIBGPGME 1 )
else()
set( HAVE_LIBGPGME 1 )
endif( NOT GPGME_FOUND )
endif( WITH_GPGME )
##### check for aRts
if( WITH_ARTS )
pkg_search_module( ARTS arts )
pkg_search_module( ARTSC artsc )
find_library( ARTSKDE artskde )
if( ARTSKDE )
set( ARTSKDE_LIBRARIES artskde-shared )
endif()
if( (NOT ARTS_FOUND) OR (NOT ARTSKDE) )
tde_message_fatal( "aRts support has been requested but was not found on your system." )
else()
set( WITH_ARTS 1 )
endif()
endif( WITH_ARTS )
##### check for libart-lgpl
if ( WITH_LIBART )
pkg_search_module( LIBART libart libart_lgpl libart-2.0 )
if( NOT LIBART_FOUND )
tde_message_fatal( "Libart support has been requested but was not found on your system." )
else()
set( HAVE_LIBART 1 )
endif()
endif( WITH_LIBART )
##### check for kontact
if( BUILD_KONTACT_PLUGIN )
find_file( HAVE_KONTACT_HEADER "kontact/core.h" )
if( NOT HAVE_KONTACT_HEADER )
tde_message_fatal( "kontact plugin support has been requested but kontact headers were not found on your system." )
endif()
endif( BUILD_KONTACT_PLUGIN )

6
backgrounds-previews/CMakeLists.txt

@ -0,0 +1,6 @@
file( GLOB _pngs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.png )
install(
FILES ${_pngs}
DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}/backgrounds/previews
)

6
backgrounds/CMakeLists.txt

@ -0,0 +1,6 @@
file( GLOB _pngs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.png )
install(
FILES ${_pngs} alien-artifact.png.config
DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}/backgrounds
)

17
config.h.cmake

@ -0,0 +1,17 @@
#define VERSION "@VERSION@"
// Defined if you have fvisibility and fvisibility-inlines-hidden support.
#cmakedefine __KDE_HAVE_GCC_VISIBILITY 1
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#cmakedefine WORDS_BIGENDIAN @WORDS_BIGENDIAN@
/* Defined if you have the libgpgme library */
#cmakedefine HAVE_LIBGPGME 1
/* Defined if you have the aRts library */
#cmakedefine WITH_ARTS 1
/* Defined if you have the libart-lgpl library */
#cmakedefine HAVE_LIBART 1

14
doc/CMakeLists.txt

@ -0,0 +1,14 @@
file( GLOB _dirs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} * )
string( REGEX REPLACE "[ \r\n\t]+" ";" _linguas "$ENV{LINGUAS}" )
foreach( _dir ${_dirs} )
if( IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/${_dir} AND
EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_dir}/CMakeLists.txt )
if( "${_dir}" STREQUAL "en" OR
"${_dir}" STREQUAL "man" OR
"${_linguas}" MATCHES "^;*$" OR
";${_linguas};" MATCHES ";${_dir};" )
add_subdirectory( ${_dir} )
endif( )
endif()
endforeach()

1
doc/en/CMakeLists.txt

@ -0,0 +1 @@
tde_create_handbook( DESTINATION ${PROJECT_NAME} )

5
doc/man/CMakeLists.txt

@ -0,0 +1,5 @@
INSTALL(
FILES ${PROJECT_NAME}.1
DESTINATION ${MAN_INSTALL_DIR}/man1
COMPONENT doc
)

171
doc/man/basket.1

@ -0,0 +1,171 @@
.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36.
.TH BasKet "1" "February 2007" "BasKet 1.0"
.SH NAME
BasKet
.SH SYNOPSIS
.B basket
[\fIQt-options\fR] [\fITDE-options\fR] [\fIoptions\fR] [\fIfile\fR]
.SH DESCRIPTION
BasKet is a application to allow you to quickly take notes, save your ideas and assist in quickly find them later.
Organizing your notes has never been so easy.
Basket also allows integration with Kontact and rest of TDE environment.
.SH OPTIONS
.SS "BasKet options:"
.TP
\fB\-d\fR, \fB\-\-debug\fR
Show the debug window
.HP
\fB\-f\fR, \fB\-\-data\-folder\fR <folder> Custom folder where to load and save basket data and application data (useful for debugging purpose)
.TP
\fB\-h\fR, \fB\-\-start\-hidden\fR
Hide the main window in the system tray icon on startup
.TP
\fB\-k\fR, \fB\-\-use\-drkonquy\fR
When crashing, use the standard TDE report dialog instead of sending an email
.SS "Arguments:"
.TP
file
Open basket archive or template
.SS "Generic options:"
.TP
\fB\-\-help\fR
Show help about options
.TP
\fB\-\-help\-qt\fR
Show Qt specific options
.TP
\fB\-\-help\-tde\fR
Show TDE specific options
.TP
\fB\-\-help\-all\fR
Show all options
.TP
\fB\-\-author\fR
Show author information
.TP
\fB\-v\fR, \fB\-\-version\fR
Show version information
.TP
\fB\-\-license\fR
Show license information
.TP
\fB\-\-\fR
End of options
.SS "Qt options:"
.TP
\fB\-\-display\fR <displayname>
Use the X\-server display 'displayname'
.TP
\fB\-\-session\fR <sessionId>
Restore the application for the given 'sessionId'
.TP
\fB\-\-cmap\fR
Causes the application to install a private color
map on an 8\-bit display
.TP
\fB\-\-ncols\fR <count>
Limits the number of colors allocated in the color
cube on an 8\-bit display, if the application is
using the QApplication::ManyColor color
specification
.TP
\fB\-\-nograb\fR
tells Qt to never grab the mouse or the keyboard
.TP
\fB\-\-dograb\fR
running under a debugger can cause an implicit
\fB\-nograb\fR, use \fB\-dograb\fR to override
.TP
\fB\-\-sync\fR
switches to synchronous mode for debugging
.TP
\fB\-\-fn\fR, \fB\-\-font\fR <fontname>
defines the application font
.TP
\fB\-\-bg\fR, \fB\-\-background\fR <color> sets the default background color and an
application palette (light and dark shades are
calculated)
.HP
\fB\-\-fg\fR, \fB\-\-foreground\fR <color> sets the default foreground color
.TP
\fB\-\-btn\fR, \fB\-\-button\fR <color>
sets the default button color
.TP
\fB\-\-name\fR <name>
sets the application name
.TP
\fB\-\-title\fR <title>
sets the application title (caption)
.TP
\fB\-\-visual\fR TrueColor
forces the application to use a TrueColor visual on
an 8\-bit display
.TP
\fB\-\-inputstyle\fR <inputstyle> sets XIM (X Input Method) input style. Possible
values are onthespot, overthespot, offthespot and
root
.TP
\fB\-\-im\fR <XIM server>
set XIM server
.TP
\fB\-\-noxim\fR
disable XIM
.TP
\fB\-\-reverse\fR
mirrors the whole layout of widgets
.SS "TDE options:"
.TP
\fB\-\-caption\fR <caption>
Use 'caption' as name in the titlebar
.TP
\fB\-\-icon\fR <icon>
Use 'icon' as the application icon
.TP
\fB\-\-miniicon\fR <icon>
Use 'icon' as the icon in the titlebar
.TP
\fB\-\-config\fR <filename>
Use alternative configuration file
.TP
\fB\-\-dcopserver\fR <server>
Use the DCOP Server specified by 'server'
.TP
\fB\-\-nocrashhandler\fR
Disable crash handler, to get core dumps
.TP
\fB\-\-waitforwm\fR
Waits for a WM_NET compatible windowmanager
.TP
\fB\-\-style\fR <style>
sets the application GUI style
.TP
\fB\-\-geometry\fR <geometry>
sets the client geometry of the main widget \- see man X for the argument format
.TP
\fB\-\-nofork\fR
Don't run in the background.
.SH "SEE ALSO"
The full documentation for
.B BasKet:
is maintained as a TDE help file.
If TDE, Konqueror and KHelpcenter is fully installed on your computer, accessing
.IP
.B help:/basket
.PP
should give you access to the complete manual.
.SH "AUTHOR"
.B BasKet
Note Pads was written by
.IP
S\['e]bastien Lao\[^u]t <slaout@linux62.org>
.IP
Petri Damst\['e]n <damu@iki.fi>
.IP
Alex Gontmakher <gsasha@cs.technion.ac.il>
.IP
Marco Martin <m4rt@libero.it>
.PP
Please report bugs to slaout@linux62.org.
.SH "OTHER"
This manpage is derived from help2man by Sune Vuorela <debian@pusling.com> for the Debian project (But may be used by others). License: GPL2 like BasKet

62
file-integration/CMakeLists.txt

@ -0,0 +1,62 @@
include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${TDE_INCLUDE_DIR}
${TQT_INCLUDE_DIRS}
)
link_directories(
${TQT_LIBRARY_DIRS}
${TDE_LIB_DIR}
)
##### basketthumbcreator (kpart)
tde_add_kpart( basketthumbcreator MODULE AUTOMOC
SOURCES
basketthumbcreator.cpp
LINK
tdecore-shared
tdeui-shared
tdeio-shared
kjs-shared
DESTINATION ${PLUGIN_INSTALL_DIR}
)
##### icons
tde_install_icons()
##### other data
add_custom_command(
OUTPUT basket.magic.mgc
COMMAND ${FILE_EXECUTABLE} -C -m ${CMAKE_CURRENT_SOURCE_DIR}/basket.magic
)
add_custom_target(
basket_magic_mgc
ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/basket.magic.mgc
)
install(
FILES basket.magic ${CMAKE_CURRENT_BINARY_DIR}/basket.magic.mgc
DESTINATION ${CONFIG_INSTALL_DIR}/magic
)
install(
FILES x-basket-archive.desktop x-basket-template.desktop
DESTINATION ${MIME_INSTALL_DIR}/application
)
install(
FILES basketthumbcreator.desktop
DESTINATION ${SERVICES_INSTALL_DIR}
)

6
images/CMakeLists.txt

@ -0,0 +1,6 @@
file( GLOB _pngs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.png )
install(
FILES ${_pngs}
DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}/images
)

72
kontact_plugin/CMakeLists.txt

@ -0,0 +1,72 @@
include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_SOURCE_DIR}/src
${CMAKE_BINARY_DIR}kontact_plugin
${TDE_INCLUDE_DIR}
${TQT_INCLUDE_DIRS}
)
link_directories(
${TQT_LIBRARY_DIRS}
${TDE_LIB_DIR}
)
###### basketdcopiface stub for kontact plugin
set( KIDL_OUTPUT basketdcopiface.kidl )
add_custom_command(
OUTPUT ${KIDL_OUTPUT}
COMMAND ${KDE3_DCOPIDL_EXECUTABLE} ${CMAKE_SOURCE_DIR}/src/basketdcopiface.h > ${KIDL_OUTPUT}
DEPENDS ${CMAKE_SOURCE_DIR}/src/basketdcopiface.h
)
add_custom_target(
kontact-basketdcopiface-kidl
DEPENDS ${KIDL_OUTPUT}
)
add_custom_command(
OUTPUT basketdcopiface_stub.cpp basketdcopiface_stub.h
COMMAND ${KDE3_DCOPIDL2CPP_EXECUTABLE} --c++-suffix cpp --no-signals --no-skel ${KIDL_OUTPUT}
DEPENDS kontact-basketdcopiface-kidl
)
add_custom_target(
kontact-basketdcopiface-stub
DEPENDS basketdcopiface_stub.cpp basketdcopiface_stub.h
)
##### libkontact_basket (kpart)
tde_add_kpart( libkontact_basket AUTOMOC
SOURCES
basket_plugin.cpp
uniqueapphandler.cpp
${CMAKE_CURRENT_BINARY_DIR}/basketdcopiface_stub.cpp
LINK
tdecore-shared
tdeui-shared
kpinterfaces
DESTINATION ${PLUGIN_INSTALL_DIR}
DEPENDENCIES kontact-basketdcopiface-stub
)
##### other data
install(
FILES kontact_basketplugin.setdlg
DESTINATION ${DATA_INSTALL_DIR}/kontact/ksettingsdialog
)
install(
FILES basket.desktop
DESTINATION ${SERVICES_INSTALL_DIR}/kontact
)

14
po/CMakeLists.txt

@ -0,0 +1,14 @@
file( GLOB_RECURSE po_files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.po )
string( REGEX REPLACE "[ \r\n\t]+" ";" _linguas "$ENV{LINGUAS}" )
foreach( _po ${po_files} )
get_filename_component( _lang ${_po} NAME_WE )
if( "${_linguas}" MATCHES "^;*$" OR ";${_linguas};" MATCHES ";${_lang};" )
if( "${_po}" MATCHES "^([^/]*)/.*" )
string( REGEX REPLACE "^([^/]*)/.*" "\\1" _component "${_po}" )
else( )
set( _component "${PROJECT_NAME}" )
endif( )
tde_create_translation( FILES ${_po} LANG ${_lang} OUTPUT_NAME ${_component} )
endif( )
endforeach( )

138
src/CMakeLists.txt

@ -0,0 +1,138 @@
include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${TDE_INCLUDE_DIR}
${TQT_INCLUDE_DIRS}
${X11_INCLUDE_DIR}
${GPGME_INCLUDE_DIRS}
${ARTS_INCLUDE_DIRS}
${LIBART_INCLUDE_DIRS}
)
link_directories(
${TQT_LIBRARY_DIRS}
${TDE_LIB_DIR}
)
##### basketcommon (shared)
tde_add_library( basketcommon SHARED AUTOMOC
SOURCES
kicondialogui.ui passwordlayout.ui basketdcopiface.skel
archive.cpp bnpview.cpp settings.cpp basket.cpp
basketproperties.cpp linklabel.cpp variouswidgets.cpp
xmlwork.cpp keyboard.cpp global.cpp exporterdialog.cpp
htmlexporter.cpp notefactory.cpp softwareimporters.cpp
focusedwidgets.cpp popupmenu.cpp basketfactory.cpp
tag.cpp qeffects.cpp kcolorcombo2.cpp newbasketdialog.cpp
tagsedit.cpp formatimporter.cpp note.cpp notecontent.cpp
notedrag.cpp noteedit.cpp filter.cpp tools.cpp
backgroundmanager.cpp regiongrabber.cpp kicondialog.cpp
kiconcanvas.cpp kgpgme.cpp likeback.cpp crashhandler.cpp
password.cpp colorpicker.cpp basketlistview.cpp
debugwindow.cpp systemtray.cpp aboutdata.cpp
basketstatusbar.cpp clickablelabel.cpp backup.cpp
LINK
tdecore-shared
tdeui-shared
tdeio-shared
tdeparts-shared
kjs-shared
${ARTSC_LIBRARIES}
${ARTSKDE_LIBRARIES}
${GPGME_LIBRARIES}
DESTINATION ${LIB_INSTALL_DIR}
)
##### basket (executable)
tde_add_executable( ${PROJECT_NAME} AUTOMOC
SOURCES
main.cpp
mainwindow.cpp
application.cpp
LINK
tdecore-shared
tdeui-shared
tdeutils-shared
kjs-shared
${ARTSC_LIBRARIES}
${ARTSKDE_LIBRARIES}
basketcommon-shared
DESTINATION ${BIN_INSTALL_DIR}
)
##### libbasketpart (kpart)
tde_add_kpart( libbasketpart MODULE AUTOMOC
SOURCES
basket_part.cpp
LINK
tdecore-shared
tdeui-shared
tdeparts-shared
kjs-shared
${ARTSC_LIBRARIES}
${ARTSKDE_LIBRARIES}
basketcommon-shared
DESTINATION ${PLUGIN_INSTALL_DIR}
)
##### kcm_basket (kpart)
tde_add_kpart( kcm_basket MODULE AUTOMOC
SOURCES
kcm_basket.cpp
LINK
tdecore-shared
tdeui-shared
kjs-shared
${ARTSC_LIBRARIES}
${ARTSKDE_LIBRARIES}
basketcommon-shared
DESTINATION ${PLUGIN_INSTALL_DIR}
)
##### icons
tde_install_icons()
##### other data
install(
FILES basketui.rc basket_part.rc
DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}
)
install(
FILES
basket_part.desktop
basket_config_general.desktop
basket_config_baskets.desktop
basket_config_new_notes.desktop
basket_config_notes_appearance.desktop
basket_config_apps.desktop
DESTINATION ${SERVICES_INSTALL_DIR}
)
install(
FILES ${PROJECT_NAME}.desktop
DESTINATION ${XDG_APPS_INSTALL_DIR}
)

3
tags/CMakeLists.txt

@ -0,0 +1,3 @@
tde_install_icons()
#tde_install_icons( DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}/icons )

6
welcome/CMakeLists.txt

@ -0,0 +1,6 @@
file( GLOB _files RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.baskets )
install(
FILES ${_files}
DESTINATION ${DATA_INSTALL_DIR}/${PROJECT_NAME}/welcome
)
Loading…
Cancel
Save