Top-2.3.4/0000755000175000017500000000000013165413647010376 5ustar hlehleTop-2.3.4/Top.spec.cmake0000644000175000017500000000110013101037227013045 0ustar hlehle%define ver @TOP_VERSION@ %define rel 0 %define prefix /usr Summary: running processes control Name: Top Version: %{ver} Release: %{rel} License: GPL Group: User Interface/X Source: %{name}-%{ver}.tar.gz BuildRoot: /var/tmp/%{name}-buildroot %description running processes control %prep %setup -q -n %{name}-%{ver} %{rel} %build cmake -DCMAKE_INSTALL_PREFIX=%{prefix} . make -j4 %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc COPYING INSTALL %{prefix}/bin/Top %changelog Top-2.3.4/Top.desktop0000644000175000017500000000023613101037227012516 0ustar hlehle[Desktop Entry] GenericName=System Monitor Name=Top MimeType=application/x-ksysguard; Exec=Top Icon=Top Type=Application Terminal=false Categories=Qt;System; Top-2.3.4/base-help/0000755000175000017500000000000013136572002012223 5ustar hlehleTop-2.3.4/base-help/DefaultHelpText.h0000644000175000017500000000314113110773535015443 0ustar hlehle#ifndef DefaultHelpText_h #define DefaultHelpText_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include namespace Base { //* default help text static const QString helpText[] = { //_________________________________________________________ QObject::tr( "Contact" ), QObject::tr( "

Contact

\n" "

Latest software versions can be downloaded at:

" "

http://www.phenix.bnl.gov/WWW/publish/hpereira/software/index.php?page=introduction

" "

For suggestions and bug reports, please contact the author directly at:

" "

hugo.pereira@free.fr

" ), 0 }; }; #endif Top-2.3.4/base-help/HelpModel.h0000644000175000017500000000370613126214754014261 0ustar hlehle#ifndef HelpModel_h #define HelpModel_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "ListModel.h" #include "HelpItem.h" #include "Debug.h" #include namespace Base { //* model for help items class HelpModel: public ListModel, private Counter { //* Qt meta object declaration Q_OBJECT public: //* number of columns enum { nColumns = 1 }; //* constructor explicit HelpModel(): Counter( "HelpModel" ) {} //*@name methods reimplemented from base class //@{ //* flags Qt::ItemFlags flags(const QModelIndex &index) const override; // return data for a given index QVariant data(const QModelIndex &index, int role) const override; //* header data QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override { return QVariant(); } //* number of columns for a given index int columnCount(const QModelIndex &parent = QModelIndex()) const override { return nColumns; } //@} }; } #endif Top-2.3.4/base-help/HelpDialog.cpp0000644000175000017500000001057013126214754014750 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "HelpDialog.h" #include "HelpManager.h" #include "HelpManager.h" #include "HelpModel.h" #include "QuestionDialog.h" #include "Singleton.h" #include "TextEditor.h" #include "TextEditionDelegate.h" #include "TreeView.h" #include "XmlOptions.h" #include #include #include #include #include #include #include namespace Base { //_________________________________________________________ HelpDialog::HelpDialog( HelpManager& manager, QWidget *parent ): CustomDialog( parent, CloseButton ), manager_( &manager ) { Debug::Throw( "HelpDialog::HelpDialog.\n" ); // customize layout layout()->setMargin(0); layout()->setSpacing(0); buttonLayout().setMargin(5); // tell dialog to delete when close setAttribute( Qt::WA_DeleteOnClose ); setOptionName( "HELP_DIALOG" ); QHBoxLayout *layout = new QHBoxLayout; layout->setMargin(0); layout->setSpacing(2); mainLayout().addLayout( layout ); // add help list list_ = new TreeView( this ); list_->setMaximumWidth(150); layout->addWidget( list_ ); list_->setModel( &model_ ); list_->setSortingEnabled( false ); list_->header()->hide(); // stack widget to switch between html and plain text editor layout->addWidget( htmlFrame_ = new QWidget( this ) ); // vbox layout for editor and button QVBoxLayout *vLayout = new QVBoxLayout; vLayout->setMargin(0); htmlFrame_->setLayout( vLayout ); vLayout->addWidget( htmlEditor_ = new TextEditor( htmlFrame_ ) ); htmlEditor_->setReadOnly( true ); htmlEditor_->setWrapFromOptions( false ); htmlEditor_->wrapModeAction().setChecked( true ); // connect list to text edit connect( list_->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), SLOT(_display(QModelIndex,QModelIndex)) ); // add close accelerator new QShortcut( QKeySequence::Quit, this, SLOT(close()) ); connect( Base::Singleton::get().application(), SIGNAL(configurationChanged()), SLOT(_updateConfiguration()) ); _updateConfiguration(); } //_________________________________________________________ void HelpDialog::setItems( const HelpItem::List& items ) { Debug::Throw( "HelpDialog::setItems.\n" ); // clear list and editors htmlEditor_->clear(); // set items model_.set( items ); // select first index if( (!list_->selectionModel()->currentIndex().isValid()) && model_.hasIndex(0,0) ) { list_->selectionModel()->setCurrentIndex( model_.index(0,0), QItemSelectionModel::SelectCurrent | QItemSelectionModel::Rows ); } return; } //_________________________________________________________ void HelpDialog::_display( const QModelIndex& current, const QModelIndex& previous ) { Debug::Throw( "HelpDialog::_Display.\n" ); // check validity if( !current.isValid() ) htmlEditor_->clear(); else { // retrieve item const HelpItem& item( model_.get( current ) ); htmlEditor_->setHtml( item.text() ); } return; } //_________________________________________________________ void HelpDialog::_updateConfiguration() { Debug::Throw( "HelpDialog::_updateConfiguration.\n" ); htmlEditor_->setFont( qApp->font() ); } } Top-2.3.4/base-help/HelpModel.cpp0000644000175000017500000000303413110773540014602 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "HelpModel.h" #include #include namespace Base { //__________________________________________________________________ Qt::ItemFlags HelpModel::flags(const QModelIndex &index) const { if( !index.isValid() ) return Qt::ItemFlags(0); Qt::ItemFlags flags( Qt::ItemIsEnabled | Qt::ItemIsSelectable ); return flags; } //__________________________________________________________________ QVariant HelpModel::data( const QModelIndex& index, int role ) const { // check index if( contains( index ) && role == Qt::DisplayRole ) return QString( get(index).label() ); else return QVariant(); } } Top-2.3.4/base-help/CMakeLists.txt0000644000175000017500000000253713126214754015000 0ustar hlehle# $Id$ project(BASE_HELP) set(BASE_HELP_VERSION_MAJOR 1) set(BASE_HELP_VERSION_MINOR 0) set(BASE_HELP_VERSION_PATCH 0) set(BASE_HELP_VERSION ${BASE_HELP_VERSION_MAJOR}.${BASE_HELP_VERSION_MINOR}.${BASE_HELP_VERSION_PATCH}) set(BASE_HELP_SOVERSION ${BASE_HELP_VERSION_MAJOR}.${BASE_HELP_VERSION_MINOR}) ########### Qt4 configuration ######### if(USE_QT5) find_package(Qt5Widgets REQUIRED) else() find_package(Qt4 REQUIRED) include(${QT_USE_FILE}) add_definitions(${QT_DEFINITIONS}) endif() ########### includes ############### include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_SOURCE_DIR}/base) include_directories(${CMAKE_SOURCE_DIR}/base-qt) ########### links ######### set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) link_directories(${CMAKE_INSTALL_PREFIX}/lib) ########### next target ############### set(base_help_SOURCES HelpDialog.cpp HelpManager.cpp HelpModel.cpp ) if(ENABLE_SHARED) add_library(base-help SHARED ${base_help_SOURCES}) set_target_properties(base-help PROPERTIES VERSION ${BASE_HELP_VERSION} SOVERSION ${BASE_HELP_SOVERSION}) install(TARGETS base-help DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) else() add_library(base-help STATIC ${base_help_SOURCES}) endif() target_link_libraries(base-help ${QT_LIBRARIES} base base-qt) if(USE_QT5) target_link_libraries(base-help Qt5::Widgets) endif() Top-2.3.4/base-help/HelpManager.h0000644000175000017500000000434213126214754014570 0ustar hlehle#ifndef HelpManager_h #define HelpManager_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Counter.h" #include "Debug.h" #include "File.h" #include "HelpItem.h" #include #include //* help manager class namespace Base { class HelpManager:public QObject, private Counter { Q_OBJECT public: //* constructor explicit HelpManager( QObject* parent ); //*@name accessors //@{ //* install help. Put items in the menu, create associated objects void install( const HelpItem::List& items ) { items_ = items; } //* install help. Put items in the menu, create associated objects void install( const QString text[], bool clear = true ); //* list of items const HelpItem::List& items() { return items_; } //* clear help void clear() { items_.clear(); } //* set dialog caption void setWindowTitle( const QString& value ); //@} //* display action QAction& displayAction() { return *displayAction_; } protected Q_SLOTS: //* opens help dialog void _display(); private: //* dialog display action QAction* displayAction_ = nullptr; //* window title QString windowTitle_; //* complete set of help items HelpItem::List items_; }; }; #endif Top-2.3.4/base-help/HelpDialog.h0000644000175000017500000000377713126214754014430 0ustar hlehle#ifndef HelpDialog_h #define HelpDialog_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Counter.h" #include "CustomDialog.h" #include "HelpModel.h" #include #include class TextEditor; class TreeView; namespace Base { class HelpManager; //* reference manual display dialog class HelpDialog:public CustomDialog { Q_OBJECT public: //* constructor explicit HelpDialog( HelpManager& manager, QWidget *parent = nullptr ); //* clear items void clear() { model_.clear(); } //* set items void setItems( const HelpItem::List& items ); private Q_SLOTS: //* display selected help text void _display( const QModelIndex&, const QModelIndex& ); //* update configuration void _updateConfiguration(); private: //* help manager HelpManager* manager_ = nullptr; //* model HelpModel model_; //* list of help items TreeView *list_ = nullptr; //* html edition frame QWidget* htmlFrame_ = nullptr; //* read-only text editor TextEditor *htmlEditor_ = nullptr; }; }; #endif Top-2.3.4/base-help/HelpManager.cpp0000644000175000017500000000565313126214754015131 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "BaseIconNames.h" #include "CustomDialog.h" #include "Debug.h" #include "HelpDialog.h" #include "HelpManager.h" #include "IconEngine.h" #include "QtUtil.h" #include "XmlOptions.h" #include #include #include #include #include namespace Base { //_________________________________________________________ HelpManager::HelpManager( QObject* parent ): QObject( parent ), Counter( "HelpManager" ), windowTitle_( tr( "Reference Manual" ) ) { Debug::Throw( "HelpManager::HelpManager.\n" ); // actions displayAction_ = new QAction( IconEngine::get( IconNames::Help ), QString( tr( "%1 Handbook" ) ).arg( qApp->applicationName() ), this ); displayAction_->setShortcut( QKeySequence::HelpContents ); connect( displayAction_, SIGNAL(triggered()), SLOT(_display()) ); } //_________________________________________________________ void HelpManager::install( const QString text[], bool clear ) { Debug::Throw( "HelpManager::install.\n" ); // clear existing text if( clear ) HelpManager::clear(); //! loop over help text for( int i=0; !text[i].isNull(); i++ ) { QString label( text[i] ); i++; if( text[i].isNull() ) break; items_ << HelpItem( label, text[i] ); } return; } //_____________________________________________________ void HelpManager::setWindowTitle( const QString& value ) { Debug::Throw( "HelpManager::setWindowTitle.\n" ); windowTitle_ = value; displayAction().setText( value ); } //_____________________________________________________ void HelpManager::_display() { Debug::Throw( "HelpManager::_display.\n" ); // create dialog HelpDialog* dialog( new HelpDialog( *this ) ); dialog->setWindowTitle( windowTitle_ ); dialog->setItems( items_ ); dialog->centerOnWidget( qApp->activeWindow() ); dialog->show(); return; } } Top-2.3.4/base-help/HelpItem.h0000644000175000017500000000446113135370720014112 0ustar hlehle#ifndef HelpItem_h #define HelpItem_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Counter.h" #include "Debug.h" #include //* Help system namespace namespace Base { //* reference manual single entry class HelpItem final: private Counter { public: //* constructor explicit HelpItem( const QString& label = QString(), const QString& text = QString() ): Counter( "HelpItem" ), label_( label ), text_( text ) { Debug::Throw( "HelpItem::HelpItem.\n" ); } //* item label void setLabel( const QString& label ) { label_ = label; } //* label const QString& label() const { return label_; } //* item text void setText( const QString& text ) { text_ = text; } //* item text const QString& text() const { return text_; } //* shortcut to help item list using List = QList< HelpItem >; private: //* help label QString label_; //* help text QString text_; }; //* equal-to operator inline bool operator == (const HelpItem& first, const HelpItem& second) { return first.label() == second.label() && first.text() == second.text(); } //* less than operator inline bool operator < (const HelpItem& first, const HelpItem& second) { return first.label() < second.label() || (first.label() == second.label() && first.text() < second.text() ); } } #endif Top-2.3.4/base-transparency/0000755000175000017500000000000013136572002014004 5ustar hlehleTop-2.3.4/base-transparency/TransparencyConfiguration.h0000644000175000017500000000345213126214754021370 0ustar hlehle#ifndef TransparencyConfiguration_h #define TransparencyConfiguration_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Counter.h" #include "OptionWidgetList.h" #include namespace Transparency { //! transparency common configuration class TransparencyConfiguration: public QWidget, public OptionWidgetList, private Base::Counter { Q_OBJECT public: //! flags enum Flag { Foreground = 1<<0, Background = 1<<1, All = Foreground|Background }; Q_DECLARE_FLAGS( Flags, Flag ); //! constructor explicit TransparencyConfiguration( QWidget* parent, Flags = Foreground ); Q_SIGNALS: //! modified void modified(); protected: //! foreground configuration void _foregroundConfiguration( QWidget* ); //! background configuration void _backgroundConfiguration( QWidget* ); }; } #endif Top-2.3.4/base-transparency/TransparentWidget.h0000644000175000017500000001537313126214754017641 0ustar hlehle#ifndef TransparentWidget_h #define TransparentWidget_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Counter.h" #include "Margins.h" #include #include #include #include #include namespace Transparency { //* transparent widget class TransparentWidget: public QWidget, private Base::Counter { //* Qt meta object declaration Q_OBJECT public: //* constructor explicit TransparentWidget( QWidget* = nullptr, Qt::WindowFlags flags = 0 ); //*@name actions //@{ //* reload blur region action QAction& reloadBlurRegionAction() const { return *reloadBlurRegionAction_; } //* inverse colors QAction& inverseColorsAction() const { return *inverseColorsAction_; } //@} //*@name accessors //@{ //* foreground virtual const QColor& foregroundColor() const { return inverseColorsAction().isChecked() ? shadowColor_ : foregroundColor_; } //* shadow virtual const QColor& shadowColor() const { return inverseColorsAction().isChecked() ? foregroundColor_ : shadowColor_; } //* foreground intensity virtual int foregroundIntensity() const { return foregroundIntensity_; } //* shadow offset virtual int shadowOffset() const { return shadowOffset_; } //@} //*@name modifiers //@{ //* background changed void setBackgroundChanged( bool value ) { backgroundChanged_ = value; } //@} public Q_SLOTS: //* force reloading of the background virtual void setBackgroundChanged(); protected: //* foreground virtual void _setForegroundColor( const QColor& ); //* shadow virtual void _setShadowColor( const QColor& ); //* tint virtual void _setTintColor( const QColor& ); //* tint color virtual const QColor& _tintColor() const { return tintColor_; } //* shadow offset virtual void _setShadowOffset( int value ) { shadowOffset_ = value; } //* foreground intensity virtual void _setForegroundIntensity( int value ); //* background pixmap virtual QPixmap& _backgroundPixmap() { return backgroundPixmap_; } //* background pixmap virtual const QPixmap& _backgroundPixmap() const { return backgroundPixmap_; } //*@name event handlers //@{ //* resize void resizeEvent( QResizeEvent* ) override; //* show void showEvent( QShowEvent* ) override; //* paint void paintEvent( QPaintEvent* ) override; //@} //*@name margins //@{ //* margins const Base::Margins& _margins() const { return margins_; } //* clear margins void _clearMargins() { margins_.clear(); } //* margins void _setMargins( const Base::Margins& margins ) { margins_ = margins; } //* margins void _setMargins( int margins ) { margins_ = Base::Margins( margins ); } //* outer padding Base::Margins _outerPadding() const { return outerPadding_; } //* clear outer padding void _clearOuterPadding() { outerPadding_.clear(); } //* outer padding void _setOuterPadding( const Base::Margins& margins ) { outerPadding_ = margins; } //* outer padding void _setOuterPadding( int margins ) { outerPadding_ = Base::Margins( margins ); } //@} //* background changed bool _backgroundChanged() const { return backgroundChanged_; } //* paint background on devide virtual void _paintBackground( QPaintDevice&, const QRect& ); //* paint main widget on devide /*! this must be re-implemented by derived classes */ virtual void _paint( QPaintDevice&, const QRect& ) {} //* update input shape (to prevent input events in outerPadding region) virtual void _updateInputShape(); //* update blur region virtual void _updateBlurRegion( const QRegion& ); protected Q_SLOTS: //* update background pixmap virtual void _updateBackgroundPixmap(); //* update blur region virtual void _updateBlurRegion() { if( blurRegion_.isEmpty() ) blurRegion_ = rect().translated( mapTo( window(), QPoint(0,0) ) ); _updateBlurRegion( blurRegion_ ); } //* toggle inverse colors virtual void _toggleInverseColors( bool ); private Q_SLOTS: //* update configuration void _updateConfiguration(); private: //* actions void _installActions(); //*@name actions //@{ //* reload blur region QAction* reloadBlurRegionAction_ = nullptr; //* inverse colors QAction* inverseColorsAction_ = nullptr; //@} //* true if input shape is set bool hasInputShape_ = false; //* true when background needs to be reloaded bool backgroundChanged_ = true; //* foreground QColor foregroundColor_; //* shadow QColor shadowColor_; //* tint color QColor tintColor_; //* foreground intensity int foregroundIntensity_ = 255; //* shadow offset int shadowOffset_ = 0; //* margins Base::Margins margins_; //* margins Base::Margins outerPadding_; //* store last blur region QRegion blurRegion_; #if defined(Q_OS_WIN) //* widget pixmap /*! it is used as widget storage when using full translucency */ QPixmap widgetPixmap_; #endif //* background pixmap QPixmap backgroundPixmap_; }; }; #endif Top-2.3.4/base-transparency/TransparentWidget.cpp0000644000175000017500000002623113133661334020165 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "TransparentWidget.h" #include "BaseIconNames.h" #include "Color.h" #include "CompositeEngine.h" #include "IconEngine.h" #include "Singleton.h" #include "WinUtil.h" #include "XmlOptions.h" #include "XcbUtil.h" #include #if HAVE_XCB #include #include #endif namespace Transparency { //____________________________________________________________________ TransparentWidget::TransparentWidget( QWidget *parent, Qt::WindowFlags flags ): QWidget( parent, flags ), Counter( "Transparency::TransparentWidget" ) { Debug::Throw( "TransparentWidget::TransparentWidget.\n" ); /* disable all automatic background filling to optimize painting. */ setAttribute( Qt::WA_OpaquePaintEvent, true ); setAttribute( Qt::WA_StyledBackground, false ); if( Transparency::CompositeEngine::get().isAvailable() ) { setAttribute( Qt::WA_TranslucentBackground, true ); } // actions _installActions(); // configuration _updateConfiguration(); if( Base::Singleton::get().hasApplication() ) { connect( Base::Singleton::get().application(), SIGNAL(configurationChanged()), SLOT(_updateConfiguration()) ); } } //____________________________________________________________________ void TransparentWidget::setBackgroundChanged() { Debug::Throw( "TransparentWidget::setBackgroundChanged.\n" ); setBackgroundChanged( true ); update(); } //____________________________________________________________________ void TransparentWidget::_setForegroundColor( const QColor& color ) { if( !color.isValid() ) return; foregroundColor_ = color; foregroundColor_.setAlpha( foregroundIntensity_ ); } //____________________________________________________________________ void TransparentWidget::_setShadowColor( const QColor& color ) { if( !color.isValid() ) return; shadowColor_ = color; shadowColor_.setAlpha( foregroundIntensity_ ); } //____________________________________________________________________ void TransparentWidget::_setForegroundIntensity( int value ) { foregroundIntensity_ = value; if( foregroundColor_.isValid() ) foregroundColor_.setAlpha( foregroundIntensity_ ); if( shadowColor_.isValid() ) shadowColor_.setAlpha( foregroundIntensity_ ); } //____________________________________________________________________ void TransparentWidget::_setTintColor( const QColor& color ) { Debug::Throw( "TransparentWidget::_setTintColor.\n" ); if( tintColor_ == color ) return; tintColor_ = color; setBackgroundChanged( true ); } //____________________________________________________________________ void TransparentWidget::resizeEvent( QResizeEvent* event ) { setBackgroundChanged( true ); #if defined(Q_OS_WIN) if( CompositeEngine::get().isAvailable() ) { widgetPixmap_ = QPixmap( size() ); widgetPixmap_.fill( Qt::transparent ); } #endif QWidget::resizeEvent( event ); _updateInputShape(); } //____________________________________________________________________ void TransparentWidget::showEvent( QShowEvent* event ) { setBackgroundChanged( true ); update(); QWidget::showEvent( event ); _updateInputShape(); } //____________________________________________________________________ void TransparentWidget::paintEvent( QPaintEvent* event ) { Debug::Throw( "TransparentWidget::paintEvent.\n" ); #if defined(Q_OS_WIN) _paintBackground( widgetPixmap_, event->rect() ); _paint( widgetPixmap_, event->rect() ); WinUtil( this ).update( widgetPixmap_ ); #else _paintBackground( *this, event->rect() ); _paint( *this, event->rect() ); #endif } //________________________________________________________________________ void TransparentWidget::_paintBackground( QPaintDevice& device, const QRect& rect ) { Debug::Throw( "TransparentWidget::_paintBackground.\n" ); QPainter painter( &device ); painter.setClipRect( rect ); if( CompositeEngine::get().isAvailable() ) { painter.setRenderHints(QPainter::SmoothPixmapTransform); painter.setCompositionMode(QPainter::CompositionMode_Source ); } if( backgroundChanged_ ) _updateBackgroundPixmap(); if( !backgroundPixmap_.isNull() ) { painter.drawPixmap( TransparentWidget::rect(), backgroundPixmap_, TransparentWidget::rect() ); } painter.end(); } //____________________________________________________________________ void TransparentWidget::_toggleInverseColors( bool value ) { Debug::Throw( "TransparentWidget::_toggleInverseColors.\n" ); XmlOptions::get().set( "TRANSPARENCY_INVERSE_COLORS", value ); update(); } //____________________________________________________________________ void TransparentWidget::_updateConfiguration() { Debug::Throw( "TransparentWidget::_updateConfiguration.\n" ); // colors QColor color; _setForegroundColor( (color = QColor( XmlOptions::get().get("TRANSPARENCY_FOREGROUND_COLOR"))).isValid() ? color:palette().color( QPalette::WindowText ) ); _setShadowColor( QColor( XmlOptions::get().get("TRANSPARENCY_SHADOW_COLOR")) ); _setForegroundIntensity( XmlOptions::get().get( "TRANSPARENCY_FOREGROUND_INTENSITY" ) ); // shadow offset _setShadowOffset( XmlOptions::get().get("TRANSPARENCY_SHADOW_OFFSET") ); // inverse colors inverseColorsAction_->setChecked( XmlOptions::get().get( "TRANSPARENCY_INVERSE_COLORS" ) ); // tint auto tintColor = XmlOptions::get().get( "TRANSPARENCY_TINT_COLOR" ); int tintIntensity( XmlOptions::get().get( "TRANSPARENCY_TINT_INTENSITY" ) ); if( tintColor.isValid() && tintIntensity ) { tintColor.get().setAlpha( tintIntensity ); _setTintColor( tintColor ); } else _setTintColor( QColor() ); #if defined(Q_OS_WIN) // create widget pixmap when compositing is enabled if( CompositeEngine::get().isAvailable() ) { widgetPixmap_ = QPixmap( size() ); widgetPixmap_.fill( Qt::transparent ); } else widgetPixmap_ = QPixmap(); #endif // update input shape if( testAttribute(Qt::WA_WState_Created) || internalWinId() ) { _updateInputShape(); } } //____________________________________________________________________ void TransparentWidget::_updateBackgroundPixmap() { Debug::Throw( "TransparentWidget::_updateBackgroundPixmap.\n" ); backgroundPixmap_ = QPixmap( size() ); if( CompositeEngine::get().isAvailable() ) backgroundPixmap_.fill( Qt::transparent ); else if( !( tintColor_.isValid() && tintColor_.alpha() == 255 ) ) backgroundPixmap_.fill( palette().color( backgroundRole() ) ); // tint if( tintColor_.isValid() ) backgroundPixmap_.fill( tintColor_ ); setBackgroundChanged( false ); return; } //____________________________________________________________________ void TransparentWidget::_installActions() { Debug::Throw( "TransparentWidget::_installAction.\n" ); addAction( reloadBlurRegionAction_ = new QAction( IconEngine::get( IconNames::Reload ), tr( "Reload Blur Region" ), this ) ); connect( reloadBlurRegionAction_, SIGNAL(triggered()), SLOT(_updateBlurRegion()) ); addAction( inverseColorsAction_ = new QAction( tr( "Inverse Colors" ), this ) ); inverseColorsAction_->setCheckable( true ); inverseColorsAction_->setChecked( false ); connect( inverseColorsAction_, SIGNAL(toggled(bool)), SLOT(_toggleInverseColors(bool)) ); } //________________________________________________ void TransparentWidget::_updateInputShape() { #if HAVE_XCB if( !XcbUtil::isX11() ) return; // check outer padding // TODO: should remove existing shape if any // TODO: should check shape extension version if( outerPadding_.isNull() ) { if( hasInputShape_ ) { // reset shape auto connection = XcbUtil::get().connection(); xcb_shape_mask( connection, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, winId(), 0, 0, XCB_PIXMAP_NONE); xcb_flush( connection ); hasInputShape_ = false; } } else { // update shape auto rect = outerPadding_.adjustedRect( this->rect() ); xcb_rectangle_t xrect; xrect.x = rect.x(); xrect.y = rect.y(); xrect.width = rect.width(); xrect.height = rect.height(); auto connection = XcbUtil::get().connection(); xcb_shape_rectangles( connection, XCB_SHAPE_SO_SET, XCB_SHAPE_SK_INPUT, XCB_CLIP_ORDERING_YX_BANDED, winId(), 0, 0, 1, &xrect ); xcb_flush( connection ); hasInputShape_ = true; } #endif } //__________________________________________________________ void TransparentWidget::_updateBlurRegion( const QRegion& region ) { Debug::Throw() << "TransparentWidget::_updateBlurRegion" << endl; #if HAVE_XCB if( !XcbUtil::isX11() ) return; // create data blurRegion_ = region; auto&& rects = region.rects(); QVector data; for( const auto& r:rects ) { data << r.x() << r.y() << r.width() << r.height(); } // get connection and atom auto connection = XcbUtil::get().connection(); xcb_atom_t atom( *XcbUtil::get().atom( XcbDefines::_KDE_NET_WM_BLUR_BEHIND_REGION ) ); xcb_change_property( connection, XCB_PROP_MODE_REPLACE, winId(), atom, XCB_ATOM_CARDINAL, 32, data.size(), data.constData() ); xcb_flush( connection ); #endif } } Top-2.3.4/base-transparency/ShadowLabel.cpp0000644000175000017500000000347113110773540016704 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include #include "Debug.h" #include "Effects.h" #include "ShadowLabel.h" namespace Transparency { //__________________________________________________________________________________ void ShadowLabel::paintEvent( QPaintEvent* event ) { if( text().isEmpty() ) return; QPixmap pixmap( size() ); pixmap.fill( Qt::transparent ); { QPainter painter( &pixmap ); painter.setClipRect( event->rect() ); painter.setPen( palette().color( QPalette::WindowText ) ); painter.setFont( font() ); painter.drawText( contentsRect(), alignment(), text() ); painter.end(); } QPainter painter( this ); if( _shadowOffset() > 0 && _shadowColor().isValid() ) { QImage image( pixmap.toImage() ); Transparency::Effects::shadowBlur(image, _shadowOffset(), _shadowColor() ); painter.drawImage( rect().topLeft(), image); } painter.drawPixmap( rect().topLeft(), pixmap ); painter.end(); } } Top-2.3.4/base-transparency/CompositeEngine.h0000644000175000017500000000317513131365527017262 0ustar hlehle#ifndef CompositeEngine_h #define CompositeEngine_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "NonCopyable.h" namespace Transparency { //* initialize compositing, if available class CompositeEngine: private Base::NonCopyable { public: //* singleton static CompositeEngine& get(); //* availability bool isAvailable() { _initialize(); return available_; } protected: //* initialize void _initialize(); //* returns true if composition is enabled bool _compositingAvailable() const; private: //* constructor explicit CompositeEngine(); //* validity bool available_; //* initialized bool initialized_; }; }; #endif Top-2.3.4/base-transparency/CMakeLists.txt0000644000175000017500000000361613126214754016560 0ustar hlehle# $Id$ project(BASE_TRANSPARENCY) set(BASE_TRANSPARENCY_VERSION_MAJOR 1) set(BASE_TRANSPARENCY_VERSION_MINOR 0) set(BASE_TRANSPARENCY_VERSION_PATCH 0) set(BASE_TRANSPARENCY_VERSION ${BASE_TRANSPARENCY_VERSION_MAJOR}.${BASE_TRANSPARENCY_VERSION_MINOR}.${BASE_TRANSPARENCY_VERSION_PATCH}) set(BASE_TRANSPARENCY_SOVERSION ${BASE_TRANSPARENCY_VERSION_MAJOR}.${BASE_TRANSPARENCY_VERSION_MINOR}) ########### Qt configuration ######### if(USE_QT5) find_package(Qt5Widgets REQUIRED) else() find_package(Qt4 REQUIRED) include(${QT_USE_FILE}) add_definitions(${QT_DEFINITIONS}) endif() # ########### X11 ####################### if(UNIX AND NOT APPLE) find_package(XCB COMPONENTS XCB SHAPE) if( XCB_XCB_FOUND AND XCB_SHAPE_FOUND ) add_definitions(-DHAVE_XCB=1) else() add_definitions(-DHAVE_XCB=0) endif() else() add_definitions(-DHAVE_XCB=0) endif() ########### links ######### set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) link_directories(${CMAKE_INSTALL_PREFIX}/lib) ########### includes ############### include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_SOURCE_DIR}/base) include_directories(${CMAKE_SOURCE_DIR}/base-qt) ########### next target ############### set(base_transparency_SOURCES CompositeEngine.cpp ShadowLabel.cpp TransparencyConfiguration.cpp TransparentWidget.cpp ) if(ENABLE_SHARED) add_library(base-transparency SHARED ${base_transparency_SOURCES}) set_target_properties(base-transparency PROPERTIES VERSION ${BASE_TRANSPARENCY_VERSION} SOVERSION ${BASE_TRANSPARENCY_SOVERSION}) install(TARGETS base-transparency DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) else() add_library(base-transparency STATIC ${base_transparency_SOURCES}) endif() target_link_libraries(base-transparency ${XCB_LIBRARIES}) target_link_libraries(base-transparency ${QT_LIBRARIES} base-qt) if(USE_QT5) target_link_libraries(base-transparency Qt5::Widgets) endif() Top-2.3.4/base-transparency/Effects.h0000644000175000017500000001274113131357463015550 0ustar hlehle#ifndef Effects_h #define Effects_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ /*! \file Effects.h \brief some graphic effects \author Hugo Pereira \version $Revision$ \date $Date$ */ #include #include #include namespace Transparency { //! Exponential blur, Jani Huhtanen, 2006 class Effects { public: //! blur image static void shadowBlur(QImage &image, int radius, const QColor &color) { if (radius < 1) return; expBlur<16, 7>(image, radius); QPainter p(&image); p.setCompositionMode(QPainter::CompositionMode_SourceIn); p.fillRect(image.rect(), color); p.end(); } private: /* * expBlur(QImage &img, int radius) * * In-place blur of image 'img' with kernel * of approximate radius 'radius'. * * Blurs with two sided exponential impulse * response. * * aprec = precision of alpha parameter * in fixed-point format 0.aprec * * zprec = precision of state parameters * zR,zG,zB and zA in fp format 8.zprec */ template static void expBlur(QImage &img, int radius) { if(radius < 1) return; /* Calculate the alpha such that 90% of the kernel is within the radius. (Kernel extends to infinity) */ int alpha = (int)((1 << aprec) * (1.0f - std::exp(-2.3f / (radius + 1.f)))); for (int row=0; row(img, row, alpha); } for (int col=0; col(img, col, alpha); } return; } //! inner blur template static inline void blurInner(unsigned char *bptr, int &zR, int &zG, int &zB, int &zA, int alpha); //! horizontal blur template static inline void blurRow(QImage &im, int line, int alpha); //! vertical blur template static inline void blurCol(QImage &im, int col, int alpha); template static inline const T &qClamp(const T &x, const T &low, const T &high) { if (x < low) return low; else if (x > high) return high; else return x; } }; //______________________________________________________________________________ template void Effects::blurRow(QImage &im, int line, int alpha) { int zR, zG, zB, zA; QRgb *ptr = (QRgb *)im.scanLine(line); zR = *((unsigned char *)ptr ) << zprec; zG = *((unsigned char *)ptr + 1) << zprec; zB = *((unsigned char *)ptr + 2) << zprec; zA = *((unsigned char *)ptr + 3) << zprec; for (int index=1; index((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha); for (int index=im.width()-2; index>=0; index--) blurInner((unsigned char *)&ptr[index],zR,zG,zB,zA,alpha); } //______________________________________________________________________________ template void Effects::blurCol(QImage &im, int col, int alpha) { int zR, zG, zB, zA; QRgb *ptr = (QRgb *)im.bits(); ptr += col; zR = *((unsigned char *)ptr ) << zprec; zG = *((unsigned char *)ptr + 1) << zprec; zB = *((unsigned char *)ptr + 2) << zprec; zA = *((unsigned char *)ptr + 3) << zprec; for (int index=im.width(); index<(im.height()-1)*im.width(); index+=im.width()) blurInner((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha); for (int index=(im.height()-2)*im.width(); index>=0; index-=im.width()) blurInner((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha); } //______________________________________________________________________________ template void Effects::blurInner(unsigned char *bptr, int &zR, int &zG, int &zB, int &zA, int alpha) { int R, G, B, A; R = *bptr; G = *(bptr + 1); B = *(bptr + 2); A = *(bptr + 3); zR += (alpha * ((R << zprec) - zR)) >> aprec; zG += (alpha * ((G << zprec) - zG)) >> aprec; zB += (alpha * ((B << zprec) - zB)) >> aprec; zA += (alpha * ((A << zprec) - zA)) >> aprec; *bptr = zR >> zprec; *(bptr+1) = zG >> zprec; *(bptr+2) = zB >> zprec; *(bptr+3) = zA >> zprec; } }; #endif Top-2.3.4/base-transparency/TransparencyDefaultOptions.h0000644000175000017500000000335213126214754021520 0ustar hlehle#ifndef TransparencyDefaultOptions_h #define TransparencyDefaultOptions_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Color.h" #include "XmlOptions.h" //_____________________________________________________ //* default options installer void installTransparencyOptions() { // foreground XmlOptions::get().set( "TRANSPARENCY_FOREGROUND_COLOR", Base::Color( Qt::white ) ); XmlOptions::get().set( "TRANSPARENCY_FOREGROUND_INTENSITY", 255 ); // shadow XmlOptions::get().set( "TRANSPARENCY_SHADOW_COLOR", Base::Color( Qt::black ) ); XmlOptions::get().set( "TRANSPARENCY_SHADOW_OFFSET", 1 ); XmlOptions::get().set( "TRANSPARENCY_INVERSE_COLORS", false ); XmlOptions::get().set( "TRANSPARENCY_USE_GRADIENT", true ); // tint XmlOptions::get().set( "TRANSPARENCY_TINT_COLOR", Base::Color( Qt::white ) ); XmlOptions::get().set( "TRANSPARENCY_TINT_INTENSITY", 0 ); } #endif Top-2.3.4/base-transparency/CompositeEngine.cpp0000644000175000017500000000535513133661423017613 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "CompositeEngine.h" #include "Debug.h" #include "XcbUtil.h" #if HAVE_XCB #include #endif namespace Transparency { //_______________________________________________________________ CompositeEngine& CompositeEngine::get() { //! singleton static CompositeEngine singleton; return singleton; } //_______________________________________________________________ CompositeEngine::CompositeEngine(): available_( false ), initialized_( false ) { Debug::Throw( "CompositeEngine::CompositeEngine.\n" ); } //_______________________________________________________________ void CompositeEngine::_initialize() { Debug::Throw( "CompositeEngine::initialize\n" ); if( !initialized_ ) { initialized_ = true; available_ = _compositingAvailable(); } } //_______________________________________________________________ bool CompositeEngine::_compositingAvailable() const { Debug::Throw( "CompositeEngine::_compositingAvailable\n" ); #if defined(Q_OS_WIN) return true; #endif #if HAVE_XCB if( !XcbUtil::isX11() ) return false; // connection xcb_connection_t* connection( XcbUtil::get().connection() ); // atom const QString atomName( QString( "_NET_WM_CM_S%1" ).arg( XcbUtil::get().defaultScreenNumber() ) ); xcb_atom_t atom( *XcbUtil::get().atom( atomName ) ); // selection owner xcb_get_selection_owner_cookie_t cookie( xcb_get_selection_owner( connection, atom ) ); XcbUtil::ScopedPointer reply( xcb_get_selection_owner_reply( connection, cookie, nullptr ) ); return reply && reply->owner; #endif // on all other systems, return false return false; } } Top-2.3.4/base-transparency/TransparencyConfiguration.cpp0000644000175000017500000001416113126214754021722 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "TransparencyConfiguration.h" #include "CompositeEngine.h" #include "Debug.h" #include "GridLayout.h" #include "OptionCheckBox.h" #include "OptionColorDisplay.h" #include "OptionSlider.h" #include "OptionSpinBox.h" #include #include #include namespace Transparency { //________________________________________________________________________ TransparencyConfiguration::TransparencyConfiguration( QWidget* parent, Flags flags ): QWidget( parent ), OptionWidgetList( this ), Counter( "Transparency::TransparencyConfiguration" ) { Debug::Throw( "TransparencyConfiguration::TransparencyConfiguration.\n" ); if( (flags&Foreground) && (flags&Background) ) { setLayout( new QVBoxLayout ); layout()->setSpacing(5); layout()->setMargin(0); } // generic widget QWidget* box; // foreground if( flags&Foreground ) { if( flags&Background ) { box = new QGroupBox( "Foreground", this ); layout()->addWidget( box ); } else box = this; _foregroundConfiguration( box ); } // background if( flags&Background ) { if( flags&Foreground ) { box = new QGroupBox( "Background", this ); layout()->addWidget( box ); } else box = this; _backgroundConfiguration( box ); } return; } //________________________________________________________________________ void TransparencyConfiguration::_foregroundConfiguration( QWidget* parent ) { OptionColorDisplay* colorDisplay; OptionSlider* slider; OptionSpinBox* spinbox; OptionCheckBox* checkbox; GridLayout* gridLayout = new GridLayout; gridLayout->setSpacing(5); gridLayout->setMargin(5); gridLayout->setMaxCount( 2 ); gridLayout->setColumnAlignment( 0, (Qt::Alignment)(Qt::AlignRight|Qt::AlignVCenter)); parent->setLayout( gridLayout ); // foreground color gridLayout->addWidget( new QLabel( tr( "Foreground Color:" ), parent ) ); gridLayout->addWidget( colorDisplay = new OptionColorDisplay( parent, "TRANSPARENCY_FOREGROUND_COLOR" ) ); colorDisplay->setToolTip( tr( "Text/display foreground color" ) ); addOptionWidget( colorDisplay ); // shadow color gridLayout->addWidget( new QLabel( tr( "Highlight color:" ), parent ) ); gridLayout->addWidget( colorDisplay = new OptionColorDisplay( parent, "TRANSPARENCY_SHADOW_COLOR" ) ); colorDisplay->setToolTip( tr( "Text/display highlight color" ) ); addOptionWidget( colorDisplay ); // foreground intensity gridLayout->addWidget( new QLabel( tr( "Foreground intensity:" ), parent ) ); gridLayout->addWidget( slider = new OptionSlider( parent, "TRANSPARENCY_FOREGROUND_INTENSITY" ) ); slider->setScale( 1.0/2.55 ); slider->setRange( 0, 100 ); slider->setSuffix( tr( "%" ) ); slider->setToolTip( tr( "Foreground color intensity" ) ); addOptionWidget( slider ); // foreground highlight offset gridLayout->addWidget( new QLabel( tr( "Highlight size: " ), parent ) ); gridLayout->addWidget( spinbox = new OptionSpinBox( parent, "TRANSPARENCY_SHADOW_OFFSET" ) ); spinbox->setMinimum( 0 ); spinbox->setMaximum( 10 ); spinbox->setSuffix( tr( "px" ) ); spinbox->setToolTip( tr( "Offset between text shadow and text.\n" "0 means no shadow." ) ); addOptionWidget( spinbox ); // inverse colors gridLayout->addWidget( checkbox = new OptionCheckBox( tr( "Inverse colors" ), parent, "TRANSPARENCY_INVERSE_COLORS" ), 4, 1, 1, 1 ); addOptionWidget( checkbox ); checkbox->setToolTip( tr( "Inverse foreground and highlight color, typically for dark themes" ) ); } //________________________________________________________________________ void TransparencyConfiguration::_backgroundConfiguration( QWidget* parent ) { OptionColorDisplay* colorDisplay; OptionSlider* slider; GridLayout* gridLayout = new GridLayout; gridLayout->setSpacing(5); gridLayout->setMargin(5); gridLayout->setMaxCount( 2 ); gridLayout->setColumnAlignment( 0, Qt::AlignRight|Qt::AlignVCenter ); parent->setLayout( gridLayout ); // background color gridLayout->addWidget( new QLabel( tr( "Background color:" ), parent ) ); gridLayout->addWidget( colorDisplay = new OptionColorDisplay( parent, "TRANSPARENCY_TINT_COLOR" ) ); colorDisplay->setToolTip( tr( "Transparent background tint color" ) ); addOptionWidget( colorDisplay ); // background intensity gridLayout->addWidget( new QLabel( tr( "Background intensity:" ), parent ) ); gridLayout->addWidget( slider = new OptionSlider( parent, "TRANSPARENCY_TINT_INTENSITY" ) ); slider->setScale( 1.0/2.55 ); slider->setRange( 0, 100 ); slider->setSuffix( tr( "%" ) ); slider->setToolTip( tr( "Transparent background tint intensity" ) ); addOptionWidget( slider ); } } Top-2.3.4/base-transparency/TransparencyHelpText.h0000644000175000017500000000724013110773535020315 0ustar hlehle#ifndef TransparencyHelpText_h #define TransparencyHelpText_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include //* transparency help text namespace Transparency { static const QString helpText[] = { //_________________________________________________ QObject::tr( "Transparency" ), QObject::tr( "

Transparency

" "" "

This section describes the various options used to set the application transparent look-and-feel. " "These options can be modified in the Transparency panel of the configuration dialog

" "

The following options are available:

" "
    " "
  • foreground color is the default color used to display the application foreground objects (e.g. text). " "Some applications that have more complex objects to display use additional settings to allow for using multiple " "foreground colors. The foreground objects can appear semi-transparent, by merging the foreground color with the " "transparent background localed underneath. The amount by which these are merged is controlled by the foreground intensity option.
  • " "
  • shadow color is the color used to possibly draw a shadow below some foreground objects (e.g. text). " "This option is ignored if the shadow offset variable (see below) is set to zero.
  • " "
  • background color is the color possibly used on top of the transparent background. The amount of color used for the tint is controlled by " "the tint intensity option. The color is ignored if this intensity is set to zero. On the contrary if the intensity is set to its maximum " "value, the transparent background is ignored, which is effectively equivalent to disabling all transparency effects.
  • " "
  • shadow offset is the offset between foreground objects (e.g. text) and the shadow that is drawn underneath. Setting this parameter to zero disables " "the drawing of any shadow
  • " "
  • foreground intensity controls the amount of merging between the foreground color and the transparent background located " "underneath. A value of zero makes all foreground objects invisible. On the contrary a maximum value corresponds to a solid foreground " "color, meaning that the background below is not visible.
  • " "
  • tint intensity is the amount of tint color merged to the transparent background to form the application background. " "A value of zero correspond to no tint. A maximum value effectively disable transparency effects.
  • " "
" ), 0 }; }; #endif Top-2.3.4/base-transparency/ShadowLabel.h0000644000175000017500000000423413126214754016353 0ustar hlehle#ifndef ShadowLabel_h #define ShadowLabel_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Counter.h" #include #include #include namespace Transparency { class ShadowLabel: public QLabel, private Base::Counter { public: //* construct from any args that make a QLabel template< typename... Args > explicit ShadowLabel( Args&&... args ): QLabel( std::forward(args)... ), Counter( "Transparency::ShadowLabel" ), shadowOffset_( 0 ) {} //* shadow void setShadow( const QColor& color, int offset ) { setShadowColor( color ); setShadowOffset( offset ); } //* shadow offset void setShadowOffset( int value ) { shadowOffset_ = value; } //* shadow color void setShadowColor( const QColor& color ) { shadowColor_ = color; } protected: void paintEvent( QPaintEvent* ) override; private: //* shadow offset int _shadowOffset() const { return shadowOffset_; } //* shadow color const QColor& _shadowColor() const { return shadowColor_; } //* shadow offset int shadowOffset_; //* shadow color QColor shadowColor_; }; }; #endif Top-2.3.4/INSTALL0000644000175000017500000000401713101037227011413 0ustar hlehle// $Id$ /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * software; if not, write to the Free Software Foundation, Inc., 59 Temple * Place, Suite 330, Boston, MA 02111-1307 USA * * *******************************************************************************/ How to install -------------- Get a tarball of latest release and unpack: gtar -xzvf Top-xyz.tar.gz or I. cmake: --------- cd Top-xyz/ cmake . (see below or use cmake . --help for options) II. Make: --------- make make install to install the code. This will install Top in the default installation path of your system (e.g. /usr/local/bin, or /usr/bin, depending on the system). This usually requires root privileges at the installation stage. III. Local installation: ------------------------ Alternatively a different installation path can be set at configuration time using the CMAKE_INSTALL_PREFIX option. For a local installation use: cmake -DCMAKE_INSTALL_PREFIX=$HOME . Program files will be installed in $HOME/bin. IV. third party applications ---------------------------- To get gridwatch running one needs to make sure that the following commands are installed on the computer, and found by the application: Whether the correct third-party applications are known to the program can be checked in the configuration (settings) dialog - top - ps - kill Questions, comments: hugo.pereira@free.fr Top-2.3.4/base-ssh/0000755000175000017500000000000013136572002012070 5ustar hlehleTop-2.3.4/base-ssh/SshSocket.cpp0000644000175000017500000000670713126214754014522 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshSocket.h" #include "Debug.h" #include #if HAVE_SSH #include #endif namespace Ssh { //_______________________________________________________________________ Socket::Socket( QObject* parent ): BaseSocket( parent ) {} //_______________________________________________________________________ void Socket::connectToHost( void* session, const QString& host, quint16 port ) { Debug::Throw() << "Ssh::Socket::connectToHost - " << host << ":" << port << endl; // store session, host and port session_ = session; host_ = host; port_ = port; // make sure timer is running if( timer_.isActive() ) timer_.stop(); if( !_tryConnect() ) timer_.start( _latency(), this ); } //_______________________________________________________________________ bool Socket::waitForConnected( int msecs ) { // do nothing if already connected if( isConnected() ) return true; QElapsedTimer timer; timer.start(); while( msecs < 0 || timer.elapsed() < msecs ) { if( _tryConnect() ) return true; } return false; } //_______________________________________________________________________ void Socket::timerEvent( QTimerEvent* event ) { // check timer id if( event->timerId() == timer_.timerId() ) { #if HAVE_SSH if( _tryConnect() ) timer_.stop(); return; #else timer_.stop(); setErrorString( "no ssh" ); return; #endif } else return BaseSocket::timerEvent( event ); } //_______________________________________________________________________ bool Socket::_tryConnect() { if( isConnected() ) return true; #if HAVE_SSH auto session( static_cast(session_) ); auto channel = libssh2_channel_direct_tcpip( session, qPrintable( host_ ), port_ ); if( channel ) { _setChannel( channel, QIODevice::ReadWrite ); return true; } else if( libssh2_session_last_errno( session ) != LIBSSH2_ERROR_EAGAIN ) { timer_.stop(); char *errMsg(nullptr); libssh2_session_last_error(session, &errMsg, NULL, 0); setErrorString( tr( "error getting direct tcp channel: %1" ).arg( errMsg ) ); emit error( QAbstractSocket::ConnectionRefusedError ); return true; } return false; #else return true; #endif } } Top-2.3.4/base-ssh/SshFileTransferObject.cpp0000644000175000017500000003136113126214754016777 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshFileTransferObject.h" #include "Debug.h" #include "SshFileReadSocket.h" #include "SshFileWriteSocket.h" #include #include #include namespace Ssh { //____________________________________________________________________________ FileTransferObject::FileTransferObject( QObject* parent, QString remoteFilename ): QObject( parent ), Counter( "Ssh::FiletransferObject" ), remoteFilename_( remoteFilename ) { buffer_.resize(maxSize_ ); } //____________________________________________________________________________ bool FileTransferObject::connect( void* session, QIODevice::OpenMode mode ) { state_ = Uninitialized; error_.clear(); if( mode == QIODevice::ReadOnly ) { // connect to remote file and start reading sshSocket_ = new FileReadSocket( this ); connect( sshSocket_, SIGNAL(error(QAbstractSocket::SocketError)), SLOT( _processError(QAbstractSocket::SocketError)) ); connect( sshSocket_, SIGNAL(connected()), SLOT(_setConnected()) ); qobject_cast(sshSocket_)->connectToFile( session, remoteFilename_ ); return true; } else if( mode == QIODevice::WriteOnly ) { sshSocket_ = new FileWriteSocket( this ); connect( sshSocket_, SIGNAL(error(QAbstractSocket::SocketError)), SLOT( _processError(QAbstractSocket::SocketError)) ); connect( sshSocket_, SIGNAL(connected()), SLOT(_setConnected()) ); qobject_cast(sshSocket_)->connectToFile( session, remoteFilename_, fileSize_ ); return true; } else { emit error( error_ = tr( "incorrect open mode" ) ); _setFailed(); return false; } } //____________________________________________________________________________ bool FileTransferObject::fromRemote( void* session, QString localFilename) { deviceOwned_ = true; QFile* device = new QFile( localFilename, this ); emit debug( tr( "Transfering remote file %1 to local file %2" ).arg( remoteFilename_ ).arg( localFilename ) ); if( device->open( QIODevice::WriteOnly ) ) return fromRemote( session, device ); else { emit error( error_ = tr( "cannot open file %1 for writting" ).arg( localFilename ) ); _setFailed(); return false; } } //____________________________________________________________________________ bool FileTransferObject::fromRemote( void* session, QIODevice* device ) { if( isFailed() ) return false; // store device localDevice_ = device; // create socket if needed if( !sshSocket_ ) connect( session, QIODevice::ReadOnly ); else if( !qobject_cast(sshSocket_) ) { emit error( error_ = tr( "file %1 not opended for reading" ).arg( remoteFilename_ ) ); _setFailed(); return false; } if( sshSocket_->isConnected() ) _prepareReading(); else connect( sshSocket_, SIGNAL(connected()), SLOT(_prepareReading()) ); connect( sshSocket_, SIGNAL(readyRead()), SLOT(_readFromSocket()) ); connect( sshSocket_, SIGNAL(readChannelFinished()), SLOT(_closeSourceFile()) ); connect( sshSocket_, SIGNAL(readChannelFinished()), SLOT(_closeSocket()) ); _readFromSocket(); return true; } //____________________________________________________________________________ bool FileTransferObject::toRemote( void* session, QString localFilename ) { deviceOwned_ = true; emit debug( tr( "Transfering local file %1 to remote file %2" ).arg( localFilename ).arg( remoteFilename_ ) ); QFile* device = new QFile( localFilename, this ); if( device->open( QIODevice::ReadOnly ) ) return toRemote( session, device ); else { emit error( error_ = tr( "cannot open file %1 for reading" ).arg( localFilename ) ); _setFailed(); return false; } } //____________________________________________________________________________ bool FileTransferObject::toRemote( void* session, QIODevice* device ) { if( isFailed() ) return false; // store device localDevice_ = device; // connect to remote file fileSize_ = localDevice_->size(); bytesTransferred_ = 0; // create socket if needed if( !sshSocket_ ) connect( session, QIODevice::WriteOnly ); else if( !qobject_cast(sshSocket_) ) { emit error( error_ = tr( "file %1 not opended for writing" ).arg( remoteFilename_ ) ); _setFailed(); return false; } if( sshSocket_->isConnected() ) _writeToSocket(); else connect( sshSocket_, SIGNAL(connected()), SLOT(_writeToSocket()) ); return true; } //_______________________________________________________________________ bool FileTransferObject::waitForConnected( int msecs ) { Debug::Throw( "Ssh::FileTransferObject::waitForConnected.\n" ); // do nothing if socket is already closed if( isConnected() ) return !isFailed(); QElapsedTimer timer; timer.start(); while( ( msecs < 0 || timer.elapsed() < msecs ) && !(state_&(Connected|Failed)) ) { qApp->processEvents(); } return isConnected() && !isFailed(); } //_______________________________________________________________________ bool FileTransferObject::waitForCompleted( int msecs ) { Debug::Throw( "Ssh::FileTransferObject::waitForCompleted.\n" ); // do nothing if socket is already closed if( isCompleted() ) return !isFailed(); QElapsedTimer timer; timer.start(); while( ( msecs < 0 || timer.elapsed() < msecs ) && !(state_&(Completed|Failed)) ) { qApp->processEvents(); } Debug::Throw( "Ssh::FileTransferObject::waitForCompleted - done\n" ); return isCompleted() && !isFailed(); } //____________________________________________________________________________ void FileTransferObject::_processError( QAbstractSocket::SocketError ) { if( sshSocket_ ) { Debug::Throw() << sshSocket_->errorString() << endl; emit error( error_ = sshSocket_->errorString() ); } _closeSourceFile(); _closeSocket(); _setFailed(); } //____________________________________________________________________________ void FileTransferObject::_setConnected() { state_ |= Connected; emit debug( tr( "Succesfully connected to %1" ).arg( remoteFilename_ ) ); } //____________________________________________________________________________ void FileTransferObject::_prepareReading() { Debug::Throw( "Ssh::FileTransferObject::_prepareReading.\n" ); // store file size fileSize_ = qobject_cast( sshSocket_ )->fileSize(); bytesTransferred_ = 0; } //____________________________________________________________________________ void FileTransferObject::_readFromSocket() { Debug::Throw( "Ssh::FileTransferObject::_readFromSocket.\n" ); // check source file and ssh socket if( !localDevice_->isOpen() ) return; if( !sshSocket_->isConnected() ) return; // read from socket, write through ssh qint64 bytesAvailable = 0; while( (bytesAvailable = sshSocket_->bytesAvailable()) > 0 ) { qint64 bytesRead = sshSocket_->read( buffer_.data(), buffer_.size() ); // emit debug( QString( "Ssh::FileTransferObject::_readFromSocket - bytesAvailable=%1, bytesRead=%2" ).arg( bytesAvailable ).arg( bytesRead ) ); if( bytesRead < 0 ) { emit error( error_ = tr( "invalid read from ssh socket: %1" ).arg( bytesRead ) ); _closeSourceFile(); _closeSocket(); _setFailed(); return; } // truncate to the right number of bytes bytesRead = qMin( bytesRead, fileSize_ - bytesTransferred_ ); if( !bytesRead ) continue; // increment bytesTransferred_ += bytesRead; // write ssize_t bytesWritten = 0; ssize_t i = 0; do { i = localDevice_->write( buffer_.data() + bytesWritten, bytesRead - bytesWritten ); if (i < 0) { emit error( error_ = tr( "invalid write to source file: %1" ).arg( i ) ); _closeSourceFile(); _closeSocket(); _setFailed(); return; } bytesWritten += i; } while( i > 0 && bytesWritten < bytesRead ); } if( fileSize_ > 0 ) { emit transferred( fileSize_, bytesTransferred_ ); } if( fileSize_ == bytesTransferred_ ) { _closeSourceFile(); _closeSocket(); _setCompleted(); } return; } //______________________________________________________ void FileTransferObject::_writeToSocket() { Debug::Throw( "Ssh::FileTransferObject::_writeToSocket.\n" ); if( !sshSocket_->isConnected() ) return; if( !localDevice_->isOpen() ) return; // read from socket, write through ssh qint64 bytesAvailable = 0; while( (bytesAvailable = localDevice_->bytesAvailable()) > 0 ) { qint64 bytesRead = localDevice_->read( buffer_.data(), buffer_.size() ); // emit debug( QString( "Ssh::FileTransferObject::_writeToSocket - bytesAvailable=%1, bytesRead=%2" ).arg( bytesAvailable ).arg( bytesRead ) ); if( bytesRead < 0 ) { emit error( tr( "invalid read from source file: %1" ).arg( bytesRead ) ); _closeSourceFile(); _closeSocket(); _setFailed(); return; } // truncate to the right number of bytes bytesRead = qMin( bytesRead, fileSize_ - bytesTransferred_ ); if( !bytesRead ) continue; ssize_t bytesWritten = 0; ssize_t i = 0; do { i = sshSocket_->write( buffer_.data() + bytesWritten, bytesRead-bytesWritten ); Debug::Throw() << "Ssh::FileTransferObject::_writeToSocket - written: " << i << endl; if (i < 0) { emit error( tr( "invalid write to socket: %1, error: %2" ).arg( i ).arg( sshSocket_->errorString() ) ); _closeSourceFile(); _closeSocket(); _setFailed(); return; } bytesWritten += i; } while( i > 0 && bytesWritten < bytesRead ); bytesTransferred_ += bytesRead; if( fileSize_ > 0 ) { emit transferred( fileSize_, bytesTransferred_ ); } } _closeSourceFile(); { auto fileWriteSocket = qobject_cast( sshSocket_ ); fileWriteSocket->sendEof(); fileWriteSocket->waitForCompleted(); } _closeSocket(); _setCompleted(); return; } //____________________________________________________________________________ void FileTransferObject::_closeSourceFile() { if( localDevice_ && deviceOwned_ ) { localDevice_->close(); deviceOwned_ = false; } } //____________________________________________________________________________ void FileTransferObject::_closeSocket() { if( sshSocket_ ) sshSocket_->close(); } } Top-2.3.4/base-ssh/SshFileReadSocket.cpp0000644000175000017500000000717613126214754016117 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshFileReadSocket.h" #include "Debug.h" #include #if HAVE_SSH #include #endif namespace Ssh { //_______________________________________________________________________ FileReadSocket::FileReadSocket( QObject* parent ): BaseSocket( parent ) {} //_______________________________________________________________________ void FileReadSocket::connectToFile( void* session, const QString& path ) { Debug::Throw() << "Ssh::FileReadSocket::connectToFile - " << path << endl; // store session, host and port session_ = session; path_ = path; // make sure timer is running if( timer_.isActive() ) timer_.stop(); if( !_tryConnect() ) timer_.start( _latency(), this ); } //_______________________________________________________________________ bool FileReadSocket::waitForConnected( int msecs ) { // do nothing if already connected if( isConnected() ) return true; QElapsedTimer timer; timer.start(); while( msecs < 0 || timer.elapsed() < msecs ) { if( _tryConnect() ) return true; } return false; } //_______________________________________________________________________ void FileReadSocket::timerEvent( QTimerEvent* event ) { // check timer id if( event->timerId() == timer_.timerId() ) { #if HAVE_SSH if( _tryConnect() ) timer_.stop(); return; #else timer_.stop(); setErrorString( "no ssh" ); return; #endif } else return BaseSocket::timerEvent( event ); } //_______________________________________________________________________ bool FileReadSocket::_tryConnect() { if( isConnected() ) return true; Debug::Throw( "FileReadSocket::_tryConnect.\n" ); #if HAVE_SSH auto session( static_cast(session_) ); auto channel = libssh2_scp_recv( session, qPrintable( path_ ), &stat_ ); if( channel ) { _setChannel( channel, QIODevice::ReadOnly ); Debug::Throw() << "FileReadSocket::_tryConnect - connected - file size:" << stat_.st_size << endl; return true; } else if( libssh2_session_last_errno( session ) != LIBSSH2_ERROR_EAGAIN ) { timer_.stop(); char *errMsg(nullptr); libssh2_session_last_error(session, &errMsg, NULL, 0); setErrorString( tr( "error connecting to remote file %1: %2" ).arg( path_ ).arg( errMsg ) ); emit error( QAbstractSocket::ConnectionRefusedError ); return true; } return false; #else return true; #endif } } Top-2.3.4/base-ssh/SshSingleton.cpp0000644000175000017500000000330413126214754015222 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshSingleton.h" #include #if defined (Q_OS_WIN) #include #endif #if HAVE_SSH #include #endif namespace Ssh { //_______________________________________________ Singleton& Singleton::get() { static Singleton singleton; return singleton; } //_______________________________________________ Singleton::Singleton(): Counter( "Ssh::Singleton" ) { #if defined(Q_OS_WIN) // some windows specific initialization WSADATA wsadata; WSAStartup(MAKEWORD(2,0), &wsadata); #endif #if HAVE_SSH initialized_ = !libssh2_init(0); #endif } //_______________________________________________ Singleton::~Singleton() { #if HAVE_SSH if( initialized_ ) libssh2_exit(); #endif } } Top-2.3.4/base-ssh/SshBaseSocket.h0000644000175000017500000000614113126214754014752 0ustar hlehle#ifndef SshBaseSocket_h #define SshBaseSocket_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Counter.h" #include #include #include #include #include #include namespace Ssh { //* ssh socket class BaseSocket: public QIODevice, private Base::Counter { Q_OBJECT public: //* constructor explicit BaseSocket( QObject* ); //* destructor ~BaseSocket() override; //*@name accessors //@{ //* true if connected bool isConnected() const { return channel_; } //* true if channel is closed bool atEnd() const override; //* sequencial mode bool isSequential() const override { return true; } //* bytes available qint64 bytesAvailable() const override { return bytesAvailable_; } //@} //*@name modifiers //@{ //* change latency void setLatency( int latency ) { latency_ = latency; } //@} Q_SIGNALS: //* emit when connected int connected(); //* error void error(QAbstractSocket::SocketError); public Q_SLOTS: //* close void close() override; protected: //* read qint64 readData( char*, qint64 maxSize ) override; //* write qint64 writeData( const char*, qint64 maxSize ) override; //* timer event void timerEvent( QTimerEvent* ) override; //* get socket latency int _latency() const { return latency_; } //* channel void* _channel() { return channel_; } //* channel void _setChannel( void*, QIODevice::OpenMode ); private: //* try connect channel, returns true on success bool _tryConnect(); //* try read data from channel bool _tryRead(); //* ssh channel void* channel_ = nullptr; //* timer QBasicTimer timer_; //* latency int latency_ = 10; //* buffer QByteArray buffer_; //* max buffer size qint64 maxSize_ = 1<<16; //* bytes available qint64 bytesAvailable_ = 0; }; } #endif Top-2.3.4/base-ssh/SshLoginDialog.h0000644000175000017500000000364113126214754015121 0ustar hlehle#ifndef SshLoginDialog_h #define SshLoginDialog_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "CustomDialog.h" #include "LineEditor.h" #include "SshConnectionAttributes.h" #include #include namespace Ssh { class LoginDialog: public CustomDialog { //* Qt meta object declaration Q_OBJECT public: //* constructor explicit LoginDialog( QWidget* ); //*@name accessors //@{ //* connection attributes ConnectionAttributes attributes() const; //@} //*@name modifiers //@{ //* connection attributes void setAttributes( const ConnectionAttributes& ); //@} protected Q_SLOTS: //* show/hide password void _toggleShowPassword( bool ); private: //* connection attributes ConnectionAttributes attributes_; LineEditor* userNameEditor_ = nullptr; LineEditor* passwordEditor_ = nullptr; QCheckBox* rememberPaswordCheckBox_ = nullptr; QCheckBox* showPasswordCheckBox_ = nullptr; }; } #endif Top-2.3.4/base-ssh/SshUtil.h0000644000175000017500000000233013110773535013640 0ustar hlehle#ifndef SshUtil_h #define SshUtil_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include namespace Ssh { class Util { public: //* tcp options bitmask static uint32_t tcpOptions( int ); //* socket options bitmask static uint32_t socketOptions( int ); //* file descriptor bitmask static uint32_t fileDescriptorOptions( int ); }; } #endif Top-2.3.4/base-ssh/SshConnectionAttributes.cpp0000644000175000017500000000442713135315420017425 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshConnectionAttributes.h" namespace Ssh { //_________________________________________________________________ const QString ConnectionAttributes::MimeType( "ssh/connection-attributes" ); //_____________________________________________________________ bool ConnectionAttributes::isValid() const { if( host_.isEmpty() ) return false; for( const auto& tunnel:tunnels_ ) { if( !tunnel.isValid() ) return false; } return true; } //_____________________________________________________________ void ConnectionAttributes::setTunnels( const TunnelAttributes::List attributesList ) { tunnels_.clear(); for( const auto& attributes:attributesList ) { addTunnel( attributes ); } } //_____________________________________________________________ void ConnectionAttributes::addTunnel( const TunnelAttributes& attributes ) { auto iter = tunnels_.find( attributes ); if( iter != tunnels_.end() ) tunnels_.erase( iter ); tunnels_.insert( attributes ); } //_____________________________________________________________ bool operator == (const ConnectionAttributes& first, const ConnectionAttributes& second) { return first.name_ == second.name_ && first.host_ == second.host_ && first.userName_ == second.userName_ && first.tunnels_ == second.tunnels_; } } Top-2.3.4/base-ssh/SshTunnel.cpp0000644000175000017500000001067013126214754014531 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshTunnel.h" #include "Debug.h" #include "SshSocket.h" namespace Ssh { //______________________________________________________ Tunnel::Tunnel( QObject* parent, QTcpSocket* socket ): QObject( parent ), Counter( "Ssh::Tunnel" ), tcpSocket_( socket ), sshSocket_( new Socket( this ) ) { Debug::Throw( "Ssh::Tunnel::Tunnel.\n" ); buffer_.resize(maxSize_ ); connect( tcpSocket_, SIGNAL(readyRead()), SLOT(_readFromTcpSocket()) ); connect( tcpSocket_, SIGNAL(disconnected()), SLOT(close()) ); connect( sshSocket_, SIGNAL(connected()), SLOT(_readFromTcpSocket()) ); connect( sshSocket_, SIGNAL(readyRead()), SLOT(_readFromSshSocket()) ); connect( sshSocket_, SIGNAL(readChannelFinished()), SLOT(close()) ); } //______________________________________________________ void Tunnel::close() { Debug::Throw( "Ssh::Tunnel::close.\n" ); tcpSocket_->close(); sshSocket_->close(); } //______________________________________________________ void Tunnel::_readFromTcpSocket() { Debug::Throw( "Ssh::Tunnel::_readFromTcpSocket.\n" ); if( !sshSocket_->isConnected() ) return; // read from socket, write through ssh qint64 bytesAvailable = 0; while( (bytesAvailable = tcpSocket_->bytesAvailable()) > 0 ) { qint64 bytesRead = tcpSocket_->read( buffer_.data(), buffer_.size() ); emit debug( QString( "Ssh::Tunnel::_readFromTcpSocket - bytesAvailable=%1, bytesRead=%2" ).arg( bytesAvailable ).arg( bytesRead ) ); if( bytesRead < 0 ) { emit error( tr( "invalid read from tcp socket: %1" ).arg( bytesRead ) ); return; } ssize_t bytesWritten = 0; ssize_t i = 0; do { i = sshSocket_->write( buffer_.data() + bytesWritten, bytesRead-bytesWritten ); Debug::Throw() << "Ssh::Tunnel::_readFromTcpSocket - written: " << i << endl; if (i < 0) { emit error( tr( "invalid write to tcp socket: %1, error: %2" ).arg( i ).arg( sshSocket_->errorString() ) ); return; } bytesWritten += i; } while( i > 0 && bytesWritten < bytesRead ); } return; } //______________________________________________________ void Tunnel::_readFromSshSocket() { Debug::Throw( "Ssh::Tunnel::_readFromSshSocket.\n" ); // read from socket, write through ssh qint64 bytesAvailable = 0; while( (bytesAvailable = sshSocket_->bytesAvailable()) > 0 ) { qint64 bytesRead = sshSocket_->read( buffer_.data(), buffer_.size() ); emit debug( QString( "Ssh::Tunnel::_readFromSshSocket - bytesAvailable=%1, bytesRead=%2" ).arg( bytesAvailable ).arg( bytesRead ) ); if( bytesRead < 0 ) { emit error( tr( "invalid read from ssh socket: %1" ).arg( bytesRead ) ); return; } ssize_t bytesWritten = 0; ssize_t i = 0; do { i = tcpSocket_->write( buffer_.data() + bytesWritten, bytesRead - bytesWritten ); if (i < 0) { emit error( tr( "invalid write to tcp socket: %1" ).arg( i ) ); return; } bytesWritten += i; } while( i > 0 && bytesWritten < bytesRead ); } return; } } Top-2.3.4/base-ssh/SshBaseSocket.cpp0000644000175000017500000001364413126214754015313 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshBaseSocket.h" #include "Debug.h" #include #if HAVE_SSH #include #endif namespace Ssh { //_______________________________________________________________________ BaseSocket::BaseSocket( QObject* parent ): QIODevice( parent ), Counter( "Ssh::BaseSocket" ) { buffer_.resize( maxSize_ ); } //_______________________________________________________________________ BaseSocket::~BaseSocket() { close(); } //_______________________________________________________________________ bool BaseSocket::atEnd() const { // check channel if( !isConnected() ) return true; #if HAVE_SSH return libssh2_channel_eof( reinterpret_cast(channel_) ); #else return true; #endif } //_______________________________________________________________________ void BaseSocket::close() { Debug::Throw( "Ssh::BaseSocket:close.\n" ); // stop timer if( timer_.isActive() ) timer_.stop(); #if HAVE_SSH // close channel if( isConnected() ) { auto channel = reinterpret_cast(channel_); libssh2_channel_close( channel ); libssh2_channel_free( channel ); channel_ = nullptr; } #endif } //_______________________________________________________________________ qint64 BaseSocket::readData( char* data, qint64 maxSize ) { if( !( openMode() & QIODevice::ReadOnly ) ) { setErrorString( tr( "Socket is writeOnly" ) ); return -1; } if( bytesAvailable_ <= 0 ) return bytesAvailable_; const qint64 bytesRead = qMin( maxSize, bytesAvailable_ ); memcpy( data, buffer_.data(), bytesRead ); buffer_ = buffer_.mid( bytesRead ); buffer_.resize( maxSize_ ); bytesAvailable_ -= bytesRead; return bytesRead; } //_______________________________________________________________________ qint64 BaseSocket::writeData( const char* data, qint64 maxSize ) { if( !(openMode() & QIODevice::WriteOnly) ) { setErrorString( tr( "Socket is readOnly" ) ); return -1; } if( !isConnected() ) return -1; #if HAVE_SSH qint64 bytesWritten = 0; LIBSSH2_CHANNEL* channel = reinterpret_cast(channel_); while( bytesWritten < maxSize ) { const qint64 i = libssh2_channel_write( channel, data + bytesWritten, maxSize - bytesWritten ); if( i >= 0 ) bytesWritten += i; else if( i != LIBSSH2_ERROR_EAGAIN ) { setErrorString( tr( "invalid write: %1" ).arg( i ) ); return -1; } } return bytesWritten; #else setErrorString( "invalid channel" ); return -1; #endif } //_______________________________________________________________________ void BaseSocket::timerEvent( QTimerEvent* event ) { // check timer id if( event->timerId() != timer_.timerId() ) return QIODevice::timerEvent( event ); #if HAVE_SSH if( isConnected() ) _tryRead(); return; #else timer_.stop(); bytesAvailable_ = -1; setErrorString( "no ssh" ); return; #endif } //_______________________________________________________________________ void BaseSocket::_setChannel( void* channel, QIODevice::OpenMode openMode ) { // close existing channel if any if( isConnected() ) close(); // stop timer if( timer_.isActive() ) timer_.stop(); // assign open mode setOpenMode( openMode ); // assign new channel channel_ = channel; if( isConnected() ) { // start timer if( openMode&QIODevice::ReadOnly ) timer_.start( latency_, this ); // emit signal emit connected(); } } //_______________________________________________________________________ bool BaseSocket::_tryRead() { if( !isConnected() ) return false; #if HAVE_SSH // read from channel LIBSSH2_CHANNEL* channel = reinterpret_cast(channel_); qint64 length = libssh2_channel_read( channel, buffer_.data()+bytesAvailable_, maxSize_-bytesAvailable_ ); if( length == LIBSSH2_ERROR_EAGAIN ) return false ; else if( length < 0 ) { setErrorString( tr( "invalid read: %1" ).arg( length ) ); timer_.stop(); bytesAvailable_ = -1; return false; } else { bytesAvailable_ += length; emit readyRead(); } // check at end if( atEnd() ) { timer_.stop(); setErrorString( "channel closed" ); emit readChannelFinished(); } return true; #else return false; #endif } } Top-2.3.4/base-ssh/SshFileWriteSocket.h0000644000175000017500000000544413126214754015777 0ustar hlehle#ifndef SshFileWriteSocket_h #define SshFileWriteSocket_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshBaseSocket.h" #include #include #include #include #include #include namespace Ssh { //* ssh socket class FileWriteSocket: public BaseSocket { Q_OBJECT public: //* constructor explicit FileWriteSocket( QObject* ); //*@name modifiers //@{ //* connect to remote void connectToFile( void*, const QString&, quint64 size, int mode = 0644 ); //* send eof void sendEof(); //* wait for connected /** warning, this method is blocking */ bool waitForConnected( int msecs = 30000 ); //* wait for completed bool waitForCompleted( int msecs = 30000 ); //@} protected: //* timer event void timerEvent( QTimerEvent* ); private: //* command list enum Command { None, Connect, SendEof, WaitForEof, WaitForClosed }; //* add command void _addCommand( Command ); //* process pending commands bool _processCommands(); //* try connect channel, returns true on success bool _tryConnect(); //* try send eof to channel, returns true on success bool _trySendEof(); //* try wait for eof from channel, returns true on success bool _tryWaitEof(); //* try close channel, returns true on success bool _tryClose(); //* session pointer void* session_ = nullptr; //* filename QString path_; //* size quint64 size_ = 0; //* file information int mode_ = 0; //* command list using CommandList = QList; CommandList commands_; //* timer QBasicTimer timer_; }; } #endif Top-2.3.4/base-ssh/SshTunnel.h0000644000175000017500000000400413126214754014170 0ustar hlehle#ifndef SshTunnel_h #define SshTunnel_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Counter.h" #include #include #include namespace Ssh { class Socket; //* tunnel class Tunnel: public QObject, private Base::Counter { Q_OBJECT public: //* constructor explicit Tunnel( QObject*, QTcpSocket* ); //*@name accessors //@{ QTcpSocket* tcpSocket() const { return tcpSocket_; } Socket* sshSocket() const { return sshSocket_; } //@} Q_SIGNALS: //* error message void error( QString ); //* debug message void debug( QString ); public Q_SLOTS: //* close void close(); protected Q_SLOTS: //* read from tcp socket void _readFromTcpSocket(); //* read from ssh socket void _readFromSshSocket(); private: //* tcp socket QTcpSocket* tcpSocket_ = nullptr; //* ssh socket Socket* sshSocket_ = nullptr; //* buffer QByteArray buffer_; //* max buffer size qint64 maxSize_ = 16384; }; } #endif Top-2.3.4/base-ssh/CMakeLists.txt0000644000175000017500000000407713126214754014646 0ustar hlehle# $Id$ project(BASE_SSH) set(BASE_SSH_VERSION_MAJOR 1) set(BASE_SSH_VERSION_MINOR 0) set(BASE_SSH_VERSION_PATCH 0) set(BASE_SSH_VERSION ${BASE_SSH_VERSION_MAJOR}.${BASE_SSH_VERSION_MINOR}.${BASE_SSH_VERSION_PATCH}) set(BASE_SSH_SOVERSION ${BASE_SSH_VERSION_MAJOR}.${BASE_SSH_VERSION_MINOR}) ########### Qt configuration ######### if(USE_QT5) find_package(Qt5Widgets REQUIRED) find_package(Qt5Network REQUIRED) else() find_package(Qt4 REQUIRED) set(QT_USE_QTNETWORK TRUE) include(${QT_USE_FILE}) add_definitions(${QT_DEFINITIONS}) endif() ########### ssh ######### find_package( PkgConfig ) if(${PKG_CONFIG_FOUND}) pkg_check_modules(LIBSSH2 libssh2>=1.2.8) endif() if(LIBSSH2_FOUND) add_definitions(-DHAVE_SSH=1) include_directories(${LIBSSH2_INCLUDE_DIRS}) else() add_definitions(-DHAVE_SSH=0) endif() ########### includes ######### include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_SOURCE_DIR}/base) include_directories(${CMAKE_SOURCE_DIR}/base-qt) ########### links ######### set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) link_directories(${CMAKE_INSTALL_PREFIX}/lib) ########### next target ############### set(base_ssh_SOURCES SshBaseSocket.cpp SshConnection.cpp SshConnectionAttributes.cpp SshFileReadSocket.cpp SshFileTransferObject.cpp SshFileWriteSocket.cpp SshLoginDialog.cpp SshSingleton.cpp SshSocket.cpp SshTunnel.cpp SshUtil.cpp ) if(ENABLE_SHARED) add_library(base-ssh SHARED ${base_ssh_SOURCES}) set_target_properties(base-ssh PROPERTIES VERSION ${BASE_SSH_VERSION} SOVERSION ${BASE_SSH_SOVERSION}) install(TARGETS base-ssh DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) else() add_library(base-ssh STATIC ${base_ssh_SOURCES} ${base_ssh_RESOURCES_RCC}) endif() target_link_libraries(base-ssh ${QT_LIBRARIES} base base-qt) if(WIN32) # add needed libraries for sockets and inet on windows target_link_libraries(base-ssh ws2_32) endif() if(${LIBSSH2_FOUND}) target_link_libraries(base-ssh ${LIBSSH2_LIBRARIES}) endif() if(USE_QT5) target_link_libraries(base-ssh Qt5::Widgets Qt5::Network) endif() Top-2.3.4/base-ssh/SshTunnelAttributes.h0000644000175000017500000000514513135146767016256 0ustar hlehle#ifndef SshTunnelAttributes_h #define SshTunnelAttributes_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Counter.h" #include #include #include namespace Ssh { //_________________________________________________________ class TunnelAttributes: private Base::Counter { public: using Set = QSet; using List = QList; //* constructor explicit TunnelAttributes(): Counter( "Ssh::TunnelAttributes" ) {} //* destructor virtual ~TunnelAttributes() = default; //*@name accessors //@{ //* host const QString& host() const { return host_; } //* port int localPort() const { return localPort_; } //* port int remotePort() const { return remotePort_; } //* validity bool isValid() const { return !(host_.isEmpty() || localPort_ <= 0 || remotePort_ <= 0 ); } //@} //*@name modifiers //@{ //* host void setHost( const QString& host ) { host_ = host; } //* port void setLocalPort( int port ) { localPort_ = port; } //* port void setRemotePort( int port ) { remotePort_ = port; } //@} private: QString host_; int localPort_ = 0; int remotePort_ = 0; //* equal to operator friend bool operator == (const TunnelAttributes& first, const TunnelAttributes& second) { return first.localPort_ == second.localPort_; } }; //____________________________________________________ inline uint qHash( const Ssh::TunnelAttributes& attributes ) { return attributes.localPort(); } } #endif Top-2.3.4/base-ssh/SshUtil.cpp0000644000175000017500000000664313126214754014206 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshUtil.h" #include #if defined(Q_OS_WIN) #include #include #include #else #include #include #include #include #endif #include #include namespace Ssh { //____________________________________________________ uint32_t Util::tcpOptions( int socket ) { int optionNames[] = { #if !defined(Q_OS_WIN) TCP_CORK, TCP_DEFER_ACCEPT, TCP_INFO, TCP_KEEPCNT, TCP_KEEPIDLE, TCP_KEEPINTVL, TCP_LINGER2, TCP_MAXSEG, TCP_QUICKACK, TCP_SYNCNT, TCP_WINDOW_CLAMP, #endif TCP_NODELAY, 0 }; uint32_t result = 0; int bit = 0; for( int index = 0; optionNames[index]; ++index ) { #if defined( Q_OS_WIN ) char value = 0; #else int value = 0; #endif socklen_t length = 0; if( getsockopt( socket, IPPROTO_TCP, optionNames[index], &value, &length ) == 0 && value ) { result |= (1< * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Counter.h" #include #include #include #include #include namespace Ssh { class BaseSocket; class FileTransferObject: public QObject, private Base::Counter { Q_OBJECT public: //* constructor explicit FileTransferObject( QObject*, QString ); //*@name modifiers //@{ //* set file size (for writing to remote) /** it must be called before calling ::connect */ void setFileSize( qint64 fileSize ) { fileSize_ = fileSize; } using QObject::connect; //* connect to remote file bool connect( void*, QIODevice::OpenMode ); //* read (remote to local) bool fromRemote( void*, QString ); //* read (remote to local) bool fromRemote( void*, QIODevice* ); //* write (local to remote) bool toRemote( void*, QString ); //* write (local to remote) bool toRemote( void*, QIODevice* ); //* wait for connected /** warning, this method is blocking */ bool waitForConnected( int msecs = 30000 ); //* wait for transfered /** warning, this method is blocking */ bool waitForCompleted( int msecs = 30000 ); //@} //*@name accessors //@{ //* file size qint64 fileSize() const { return fileSize_; } //* bytes written qint64 bytesTransferred() const { return bytesTransferred_; } //* connection state enum State { Uninitialized = 0, Connected = 1 << 0, Completed = 1 << 1, Failed = 1 << 2 }; Q_DECLARE_FLAGS( StateMask, State ); //* state StateMask state() const { return state_; } //* true when remote file socket is connected bool isConnected() const { return state_&Connected; } //* true when transfer is completed bool isCompleted() const { return state_&Completed; } //* true when transfer has failed bool isFailed() const { return state_&Failed; } //* error string QString errorString() const { return error_; } //@} Q_SIGNALS: //* transfer percentage void transferred( qint64 size, qint64 transferred ); //* error message void error( QString ); //* debug message void debug( QString ); //* emited when transfer is completed void completed(); //* emited when transfer has failed void failed(); protected Q_SLOTS: //* process error void _processError( QAbstractSocket::SocketError ); //* mark as connected void _setConnected(); //* prepare reading void _prepareReading(); //* read from ssh socket void _readFromSocket(); //* write to ssh socket void _writeToSocket(); //* close source file, once reading is finished void _closeSourceFile(); //* close socket void _closeSocket(); private: //* set completed void _setCompleted() { if( !(state_ & Completed ) ) { state_ |= Completed; emit completed(); } } //* set failed void _setFailed() { if( !(state_ & Failed) ) { state_ |= StateMask(Failed|Completed); emit failed(); } } //* destination QString remoteFilename_; //* file size qint64 fileSize_ = 0; //* bytes read qint64 bytesTransferred_ = 0; //* source file QIODevice* localDevice_ = nullptr; //* true if source device is owned by us bool deviceOwned_ = false; //* read socket BaseSocket* sshSocket_ = nullptr; //* state StateMask state_ = Uninitialized; //* error string QString error_; //* buffer QByteArray buffer_; //* max buffer size qint64 maxSize_ = 16384; }; } Q_DECLARE_OPERATORS_FOR_FLAGS( Ssh::FileTransferObject::StateMask ); #endif Top-2.3.4/base-ssh/SshFileWriteSocket.cpp0000644000175000017500000002160513126214754016327 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshFileWriteSocket.h" #include "Debug.h" #include #if HAVE_SSH #include #endif namespace Ssh { //_______________________________________________________________________ FileWriteSocket::FileWriteSocket( QObject* parent ): BaseSocket( parent ) {} //_______________________________________________________________________ void FileWriteSocket::connectToFile( void* session, const QString& path, quint64 size, int mode ) { Debug::Throw() << "Ssh::FileWriteSocket::connectToFile - " << path << " size: " << size << endl; // store session, host and port session_ = session; path_ = path; size_ = size; mode_ = mode; // make sure timer is running if( timer_.isActive() ) timer_.stop(); _addCommand( Connect ); } //_______________________________________________________________________ void FileWriteSocket::sendEof() { _addCommand( SendEof ); _addCommand( WaitForEof ); _addCommand( WaitForClosed ); } //_______________________________________________________________________ bool FileWriteSocket::waitForConnected( int msecs ) { // do nothing if already connected if( isConnected() ) return true; QElapsedTimer timer; timer.start(); while( msecs < 0 || timer.elapsed() < msecs ) { if( !_processCommands() ) return true; } return false; } //_______________________________________________________________________ bool FileWriteSocket::waitForCompleted( int msecs ) { QElapsedTimer timer; timer.start(); while( msecs < 0 || timer.elapsed() < msecs ) { if( !_processCommands() ) return true; } return false; } //_______________________________________________________________________ void FileWriteSocket::timerEvent( QTimerEvent* event ) { // check timer id if( event->timerId() == timer_.timerId() ) { if( !_processCommands() && timer_.isActive() ) timer_.stop(); } else return BaseSocket::timerEvent( event ); } //_______________________________________________ void FileWriteSocket::_addCommand( Command command ) { Debug::Throw() << "Ssh::FileWriteSocket::_AddCommand: " << command << endl; commands_.append( command ); if( !timer_.isActive() ) timer_.start( _latency(), this ); } //_______________________________________________ bool FileWriteSocket::_processCommands() { // check empty commands list if( commands_.empty() ) return false; switch( commands_.front() ) { case Connect: { if( _tryConnect() && !commands_.empty() ) commands_.removeFirst(); return true; } case SendEof: { if( _trySendEof() && !commands_.empty() ) commands_.removeFirst(); return true; } case WaitForEof: { if( _tryWaitEof() && !commands_.empty() ) commands_.removeFirst(); return true; } case WaitForClosed: { if( _tryClose() && !commands_.empty() ) commands_.removeFirst(); return true; } default: if( !commands_.empty() ) { commands_.removeFirst(); } return true; } return false; } //_______________________________________________________________________ bool FileWriteSocket::_tryConnect() { if( isConnected() ) return true; Debug::Throw( "FileWriteSocket::_tryConnect.\n" ); #if HAVE_SSH const auto session( static_cast(session_) ); if( !session ) { setErrorString( tr( "invalid session" ) ); emit error( QAbstractSocket::ConnectionRefusedError ); return true; } const auto channel = libssh2_scp_send64( session, qPrintable( path_ ), mode_&0777, (libssh2_uint64_t) size_, 0, 0 ); if( channel ) { _setChannel( channel, QIODevice::WriteOnly ); return true; } else if( libssh2_session_last_errno( session ) != LIBSSH2_ERROR_EAGAIN ) { char *errMsg(nullptr); libssh2_session_last_error(session, &errMsg, NULL, 0); setErrorString( tr( "error connecting to remote file %1: %2" ).arg( path_ ).arg( errMsg ) ); emit error( QAbstractSocket::ConnectionRefusedError ); return true; } return false; #else return true; #endif } //_______________________________________________________________________ bool FileWriteSocket::_trySendEof() { Debug::Throw( "FileWriteSocket::_trySendEof.\n" ); #if HAVE_SSH const auto session( static_cast(session_) ); if( !session ) { setErrorString( tr( "invalid session" ) ); emit error( QAbstractSocket::ConnectionRefusedError ); return true; } const auto channel( static_cast(_channel() ) ); int result = libssh2_channel_send_eof( channel ); if( result == 0 ) return true; else if( result == LIBSSH2_ERROR_EAGAIN ) return false; else { char *errMsg(nullptr); libssh2_session_last_error(session, &errMsg, NULL, 0); setErrorString( tr( "error sending eof to remote file %1: %2" ).arg( path_ ).arg( errMsg ) ); emit error( QAbstractSocket::UnknownSocketError ); return true; } #else setErrorString( tr( "no ssh" ) ); return true; #endif } //_______________________________________________________________________ bool FileWriteSocket::_tryWaitEof() { Debug::Throw( "FileWriteSocket::_tryWaitEof.\n" ); #if HAVE_SSH const auto session( static_cast(session_) ); if( !session ) { setErrorString( tr( "invalid session" ) ); emit error( QAbstractSocket::ConnectionRefusedError ); return true; } const auto channel( static_cast(_channel() ) ); int result = libssh2_channel_wait_eof( channel ); if( result == 0 ) return true; else if( result == LIBSSH2_ERROR_EAGAIN ) return false; else { char *errMsg(nullptr); libssh2_session_last_error(session, &errMsg, NULL, 0); setErrorString( tr( "error waiting for eof from remote file %1: %2" ).arg( path_ ).arg( errMsg ) ); emit error( QAbstractSocket::UnknownSocketError ); return true; } #else setErrorString( tr( "no ssh" ) ); return true; #endif } //_______________________________________________________________________ bool FileWriteSocket::_tryClose() { Debug::Throw( "FileWriteSocket::_tryClose.\n" ); #if HAVE_SSH const auto session( static_cast(session_) ); if( !session ) { setErrorString( tr( "invalid session" ) ); emit error( QAbstractSocket::ConnectionRefusedError ); return true; } const auto channel( static_cast(_channel() ) ); int result = libssh2_channel_wait_closed( channel ); if( result == 0 ) return true; else if( result == LIBSSH2_ERROR_EAGAIN ) return false; else { char *errMsg(nullptr); libssh2_session_last_error(session, &errMsg, NULL, 0); setErrorString( tr( "error waiting for closed from remote file %1: %2" ).arg( path_ ).arg( errMsg ) ); emit error( QAbstractSocket::UnknownSocketError ); return true; } #else setErrorString( tr( "no ssh" ) ); return true; #endif } } Top-2.3.4/base-ssh/SshConnection.cpp0000644000175000017500000005604313126214754015367 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshConnection.h" #include "Debug.h" #include "File.h" #include "Sleep.h" #include "SshLoginDialog.h" #include "SshSingleton.h" #include "SshSocket.h" #include "SshTunnel.h" #include #include #include #include #include #include #if defined(Q_OS_WIN) #include #else #include #include #include #endif #include #include #if HAVE_SSH #include #endif namespace Ssh { //_______________________________________________ Connection::Connection( QObject* parent ): QObject( parent ), Counter( "Ssh::Connection" ) {} //_______________________________________________ Connection::~Connection() { disconnect(); } //_______________________________________________ bool Connection::createTunnels() { Debug::Throw( "Ssh::Connection::createTunnels.\n" ); if( !Singleton::get().initialized() ) return false; // loop over tunnel attributes for( const auto& attributes:attributes_.tunnels() ) { // create Tcp server QTcpServer* tcpServer = new QTcpServer( this ); connect( tcpServer, SIGNAL(newConnection()), SLOT(_newConnection()) ); if( !tcpServer->listen( QHostAddress::LocalHost, attributes.localPort() ) ) { const QString message = tr( "Cannot listen to localhost:%1 - error:%2") .arg( attributes.localPort() ) .arg( tcpServer->errorString() ); Debug::Throw() << "Ssh::Connection::connectTunnels - " << message << endl; _notifyError( message ); return false; } } // update state and return state_ |= TunnelCreated; return true; } //_______________________________________________ bool Connection::connect() { Debug::Throw( "Ssh::Connection::connect.\n" ); if( !Singleton::get().initialized() ) return false; #if HAVE_SSH // initialize socket sshSocket_ = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP); if( sshSocket_ == -1 ) { _notifyError( tr( "unable to create ssh socket" ) ); return false; } // make socket non blocking const int flags( fcntl(sshSocket_, F_GETFL ) ); if( flags < 0 ) { _notifyError( tr( "unable to get socket flags" ) ); return false; } if( fcntl( sshSocket_, F_SETFL, flags|O_NONBLOCK ) < 0 ) { _notifyError( tr( "unable to set socket flags" ) ); return false; } // lookup host QHostInfo::lookupHost( attributes_.host(), this, SLOT(_saveHost(QHostInfo)) ); // session if(!( session_ = libssh2_session_init() )) { Debug::Throw() << "Ssh::Connection::connect - Cannot initialize session" << endl; _notifyError( tr( "cannot initialize ssh session" ) ); return false; } // cast session auto session( static_cast(session_) ); // initialize agent agent_ = libssh2_agent_init(session); if( !agent_ ) { // do not throw error because one can connect without the agent Debug::Throw(0, "Ssh::Connection::connect - failed initializing agent.\n" ); } // update state and return state_ |= SessionCreated; // mark as non blocking libssh2_session_set_blocking(session, 0); // request handshake and agent connection addCommand( Connect ); addCommand( Handshake ); addCommand( ConnectAgent ); return true; #else return false; #endif } //_______________________________________________ bool Connection::authenticate( bool forceRequestIdentity ) { Debug::Throw( "Ssh::Connection::authenticate.\n" ); // authentication if( forceRequestIdentity ) addCommand(Connection::RequestIdentity); addCommand(Connection::LoadAuthenticationMethods); addCommand(Connection::ListIdentities); addCommand(Connection::AuthenticateWithAgent); if( !( forceRequestIdentity || attributes_.rememberPassword() ) ) { addCommand(Connection::RequestIdentity); } addCommand(Connection::AuthenticateWithPassword); return true; } //_______________________________________________________________________ bool Connection::waitForConnected( int msecs ) { // do nothing if already connected if( isConnected() ) return true; // setup host manually if not already set if( sshHost_.lookupId() < 0 ) { sshHost_ = QHostInfo::fromName( attributes_.host() ); sshHost_.setLookupId( 0 ); } // start timer QElapsedTimer timer; timer.start(); while( (msecs < 0 || timer.elapsed() < msecs) && _processCommands() ) { qApp->processEvents(); } // while( msecs < 0 || timer.elapsed() < msecs ) // { // // qApp->processEvents(); // if( !_processCommands() ) break; // Sleep::msleep( 100 ); // } return isConnected(); } //_______________________________________________ void Connection::addCommand( Command command ) { Debug::Throw() << "Ssh::Connection::AddCommand: " << command << endl; commands_.append( command ); if( !timer_.isActive() ) timer_.start( latency_, this ); } //_______________________________________________ void Connection::abortCommands() { if( timer_.isActive() ) timer_.stop(); commands_.clear(); } //_______________________________________________ void Connection::disconnect() { Debug::Throw( "Ssh::Connection::disconnect.\n" ); _disconnectChannels(); _disconnectTunnels(); _disconnectSession(); } //_______________________________________________ void Connection::_saveHost( QHostInfo host ) { sshHost_ = host; } //_______________________________________________ void Connection::_disconnectChannels() { Debug::Throw( "Ssh::Connection::_disconnectChannels.\n" ); // loop over tunnels and delete for( const auto& tunnel:findChildren() ) { tunnel->close(); tunnel->deleteLater(); } } //_______________________________________________ void Connection::_disconnectSession() { Debug::Throw( "Ssh::Connection::_disconnectSession.\n" ); #if HAVE_SSH if( state_ & (Connected|SessionCreated) ) { // disconnect agent if( agent_ ) { auto agent( static_cast(agent_) ); libssh2_agent_disconnect(agent); libssh2_agent_free(agent); agent_ = nullptr; identity_ = nullptr; }; // close session if( session_ ) { auto session( static_cast(session_) ); libssh2_session_disconnect( session, "Client disconnecting normally" ); libssh2_session_free( session ); session_ = nullptr; } // close socket if( sshSocket_ >= 0 ) { close( sshSocket_ ); sshSocket_ = -1; } state_ &= ~(Connected|SessionCreated); } #endif } //_______________________________________________ void Connection::_disconnectTunnels() { Debug::Throw( "Ssh::Connection::_disconnectTunnel.\n" ); // disconnect all tcp servers for( const auto& tcpServer:findChildren() ) { if( tcpServer->isListening() ) tcpServer->close(); tcpServer->deleteLater(); } // update state state_ &= ~TunnelCreated; } //_______________________________________________ bool Connection::isSupported() { #if HAVE_SSH return true; #else return false; #endif } //_______________________________________________ void Connection::timerEvent( QTimerEvent* event ) { if( event->timerId() == timer_.timerId() ) { if( !_processCommands() && timer_.isActive() ) timer_.stop(); } else { return QObject::timerEvent( event ); } } //_______________________________________________ bool Connection::_processCommands() { // check empty commands list if( commands_.empty() ) return false; // check session if( !session_ ) { _abortCommands( tr( "Session is invalid" ) ); return false; } // emit message if( commands_.front() != lastCommand_ ) { lastCommand_ = commands_.front(); _notifyMessage( _commandMessage( lastCommand_ ) ); } #if HAVE_SSH Debug::Throw() << "Ssh::Connection::_processCommands - processing command: " << _commandMessage(commands_.front()) << " (" << commands_.front() << ")" << endl; // cast session. It is used for almost all commands auto session( static_cast(session_) ); switch( commands_.front() ) { case Connect: { // check host if( sshHost_.lookupId() < 0 ) { Debug::Throw() << "Ssh::Connection::_processCommands - lookup failed" << endl; break; } // initialize socket address structure QHostAddress address; if( !sshHost_.addresses().isEmpty() ) address = sshHost_.addresses().front(); if( address.isNull() ) { _abortCommands( tr( "Invalid host: %1" ).arg( attributes_.host() ) ); return false; } Debug::Throw() << "Ssh::Connection::_processCommands - connection." << " Host: " << attributes_.host() << " Port: " << attributes_.port() << endl; // initialize socket address struct sockaddr_in socketAddress; socketAddress.sin_family = AF_INET; socketAddress.sin_port = htons(attributes_.port()); socketAddress.sin_addr.s_addr = htonl(address.toIPv4Address()); // try connect auto result( ::connect( sshSocket_, reinterpret_cast(&socketAddress), sizeof(struct sockaddr_in) ) ); if( !result ) { // success commands_.removeFirst(); return true; } else if( errno != EALREADY && errno != EINPROGRESS ) { _abortCommands( tr( "Cannot connect to host %1:%2 - %3" ) .arg(attributes_.host()) .arg(attributes_.port()) .arg(errno) ); return false; } } break; case Handshake: { const int result( libssh2_session_handshake( session, sshSocket_ ) ); if( !result ) { // success commands_.removeFirst(); return true; } else if( result != LIBSSH2_ERROR_EAGAIN ) { _abortCommands( tr( "Handshake failed" ) ); return false; } } break; case ConnectAgent: if( !agent_ ) { // skip if no agent is defined commands_.removeFirst(); return true; } else { // accept in all cases except EAGAIN auto agent( static_cast(agent_) ); if( libssh2_agent_connect(agent) != LIBSSH2_ERROR_EAGAIN ) { commands_.removeFirst(); return true; } } break; case RequestIdentity: { // login dialog LoginDialog dialog( nullptr ); dialog.setAttributes( attributes_ ); if( dialog.exec() ) { // get updated attributes const ConnectionAttributes attributes( dialog.attributes() ); // detect changes, save, and emit signal if needed if( ( attributes_.userName() != attributes.userName() ) || ( attributes_.password() != attributes.password() ) || ( attributes_.rememberPassword() != attributes.rememberPassword() ) ) { attributes_ = attributes; emit attributesChanged(); } commands_.removeFirst(); return true; } else { _abortCommands( tr( "Login cancelled" ) ); return false; } } break; case LoadAuthenticationMethods: { if( !(authenticationMethods_ = libssh2_userauth_list( session, qPrintable( attributes_.userName() ), attributes_.userName().size() )).isNull() ) { // success commands_.removeFirst(); return true; } else if( libssh2_session_last_errno( session ) != LIBSSH2_ERROR_EAGAIN ) { _abortCommands( tr( "Failed retrieving authentication methods" ) ); return false; } } break; case ListIdentities: if( !agent_ ) { // skip if no agent is defined commands_.removeFirst(); return true; } else if( !authenticationMethods_.contains( "publickey" ) ) { Debug::Throw( 0, "Ssh::Connection::_processCommands - public key authentication is not supported.\n" ); commands_.removeFirst(); return true; } else { // accept in all cases except EAGAIN auto agent( static_cast(agent_) ); if( libssh2_agent_list_identities( agent ) != LIBSSH2_ERROR_EAGAIN ) { identity_ = nullptr; commands_.removeFirst(); return true; } } break; case AuthenticateWithAgent: if( !agent_ ) { // skip if no agent is defined commands_.removeFirst(); return true; } else if( !authenticationMethods_.contains( "publickey" ) ) { Debug::Throw( 0, "Ssh::Connection::_processCommands - public key authentication is not supported.\n" ); commands_.removeFirst(); return true; } else { Debug::Throw() << "Ssh::Connection::_processCommands - identity: " << identity_ << endl; auto agent( static_cast(agent_) ); auto identity( static_cast( identity_ ) ); if( identity ) { // cast const int result( libssh2_agent_userauth( agent, qPrintable( attributes_.userName() ), identity ) ); if( !result ) { // success commands_.removeFirst(); state_ |= Connected; commands_.clear(); emit connected(); return false; } else if( result == LIBSSH2_ERROR_EAGAIN ) { // try again break; } else { Debug::Throw() << "Ssh::Connection::authenticateWithAgent -" << " User: " << attributes_.userName() << " Key: " << identity->comment << " failed" << endl; } } // load next identity struct libssh2_agent_publickey* nextIdentity; if( libssh2_agent_get_identity( agent, &nextIdentity, identity ) ) { identity_ = nullptr; commands_.removeFirst(); return true; } else identity_ = nextIdentity; } break; case AuthenticateWithPassword: if( !authenticationMethods_.contains( "password" ) ) { // check authentication methods Debug::Throw( 0, "Ssh::Connection::_processCommands - password authentication is not supported.\n" ); commands_.removeFirst(); return true; } else { Debug::Throw() << "Ssh::Connection::_processCommands - password authentication." << " Host: " << attributes_.host() << " User: " << attributes_.userName() << " Password: " << attributes_.password() << endl; const int result( libssh2_userauth_password( session, qPrintable( attributes_.userName() ), qPrintable( attributes_.password() ) ) ); if( !result ) { // success commands_.removeFirst(); state_ |= Connected; commands_.clear(); emit connected(); return false; } else if( result != LIBSSH2_ERROR_EAGAIN ) { commands_.clear(); emit loginFailed(); // start over _disconnectSession(); connect(); authenticate( true ); return true; } } break; default: commands_.removeFirst(); return true; } return true; #else _abortCommands( tr( "No SSH support" ) ); return false; #endif } //_______________________________________________ void Connection::_notifyError( QString error ) { Debug::Throw(0) << "Ssh::Connection::_notifyError: " << error << endl; error_ = error; emit this->error( error ); } //_______________________________________________ void Connection::_notifyMessage( QString message ) { Debug::Throw() << "Ssh::Connection::_notifyMessage: " << message << endl; emit this->message( message ); } //_______________________________________________ void Connection::_notifyDebug( QString message ) { Debug::Throw() << message << endl; } //_______________________________________________ void Connection::_newConnection() { Debug::Throw( "Ssh::Connection::_newConnection.\n" ); // check session if( !session_ ) { Debug::Throw(0, "Ssh::Connection::_newConnection - invalid session.\n" ); return; } // loop over tcp servers for( const auto& tcpServer:findChildren() ) { // check pending connection if( !tcpServer->hasPendingConnections() ) continue; // find tunnel attributes matching host TunnelAttributes attributes; attributes.setLocalPort( tcpServer->serverPort() ); auto iter( attributes_.tunnels().constFind( attributes ) ); if( iter == attributes_.tunnels().end() ) { Debug::Throw(0) << "Ssh::Connection::_newConnection - unable to find tunnel attributes matching port " << tcpServer->serverPort() << endl; continue; } while( QTcpSocket* tcpSocket = tcpServer->nextPendingConnection() ) { Tunnel* tunnel = new Tunnel( this, tcpSocket ); tunnel->sshSocket()->connectToHost( session_, iter->host(), iter->remotePort() ); connect( tunnel, SIGNAL(error(QString)), SLOT(_notifyError(QString)) ); connect( tunnel, SIGNAL(debug(QString)), SLOT(_notifyDebug(QString)) ); connect( tunnel->sshSocket(), SIGNAL(error(QAbstractSocket::SocketError)), tunnel, SLOT(deleteLater()) ); connect( tunnel->sshSocket(), SIGNAL(readChannelFinished()), tunnel, SLOT(deleteLater()) ); } } } //_______________________________________________ QString Connection::_commandMessage( Command command ) const { switch( command ) { case Connect: return tr( "Connecting to host" ); case Handshake: return tr( "Performing SSH handshake" ); case ConnectAgent: return tr( "Connecting to SSH agent" ); case RequestIdentity: return tr( "Waiting for user authentication" ); case LoadAuthenticationMethods: return tr( "Loading authentication methods" ); case ListIdentities: return tr( "Loading existing identities" ); case AuthenticateWithAgent: return tr( "Trying to authenticate using SSH agent" ); case AuthenticateWithPassword: return tr( "Trying to authenticate using password" ); default: return QString(); } } //_______________________________________________ void Connection::_abortCommands( const QString& errorMessage ) { Debug::Throw( "Ssh::Connection::_abortCommands.\n" ); if( timer_.isActive() ) timer_.stop(); commands_.clear(); _notifyError( errorMessage ); } } Top-2.3.4/base-ssh/SshSingleton.h0000644000175000017500000000302513131635402014660 0ustar hlehle#ifndef SshSingleton_h #define SshSingleton_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Counter.h" #include "NonCopyable.h" namespace Ssh { //* singleton, to handle ssh allocation and freeing class Singleton final: private Base::Counter, private Base::NonCopyable { public: //* destructor ~Singleton(); //* accessor static Singleton& get(); //* true if initialized bool initialized() const { return initialized_; } //* initialize void initialize(); private: //* constructor explicit Singleton(); //* true if initalized bool initialized_ = false; }; } #endif Top-2.3.4/base-ssh/SshConnection.h0000644000175000017500000001322113126214754015023 0ustar hlehle#ifndef SshConnection_h #define SshConnection_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Counter.h" #include "SshConnectionAttributes.h" #include "SshTunnelAttributes.h" #include "WeakPointer.h" #include #include #include #include #include namespace Ssh { //_________________________________________________________ class Connection: public QObject, private Base::Counter { Q_OBJECT public: //* constructor explicit Connection( QObject* ); //* destructor ~Connection() override; //*@name accessors //@{ //* connection attributes const ConnectionAttributes& attributes() const { return attributes_; } //* session void* session() const { return session_; } //* connection state enum State { Uninitialized = 0, TunnelCreated = 1<<0, SessionCreated = 1<<1, Connected = 1<<2 }; Q_DECLARE_FLAGS( StateMask, State ); StateMask state() const { return state_; } //* true if connected bool isConnected() const { return state_ & Connected; } //* true if disconnected bool isDisconnected() const { return !(state_ & (TunnelCreated|SessionCreated|Connected) ); } //* true if connecting bool isConnecting() const { return !(isDisconnected() || isConnected() ); } //* error string QString errorString() const { return error_; } //@} //*@name modifiers //@{ using QObject::connect; //* set connection attributes void setAttributes( const ConnectionAttributes& attributes ) { attributes_ = attributes; } //* tunnels bool createTunnels(); //* connect bool connect(); //* wait for connected /** warning, this method is blocking */ bool waitForConnected( int msecs = 30000 ); //* authenticate bool authenticate( bool forceRequestIdentity = false ); //* command list enum Command { None, Connect, Handshake, ConnectAgent, RequestIdentity, LoadAuthenticationMethods, ListIdentities, AuthenticateWithAgent, AuthenticateWithPassword }; //* add command void addCommand( Command ); //* abort commands /* warning, if happens while SshInterface is in timer event, this might cause crash */ void abortCommands(); //* disconnect void disconnect(); //@} //* true if ssh is supported static bool isSupported(); Q_SIGNALS: //* message void message( const QString& ); //* error message void error( const QString& ); //* attributes updated void attributesChanged(); //* connected void connected(); //* login failed void loginFailed(); protected: //* timer event void timerEvent( QTimerEvent* ) override; protected Q_SLOTS: //* save host info lookup void _saveHost( QHostInfo ); //* disconnect channels void _disconnectChannels(); //* disconnect session void _disconnectSession(); //* disconnect tunnel void _disconnectTunnels(); //* message handling void _notifyMessage( QString ); //* error handling void _notifyError( QString ); //* error handling void _notifyDebug( QString ); //* new tcp connection (from QTcpServer) void _newConnection(); private: //* get message command QString _commandMessage( Command ) const; //* process pending commands bool _processCommands(); //* abort all commands void _abortCommands( const QString& ); //* ssh socket int sshSocket_ = -1; //* ssh session void* session_ = nullptr; //* agent void* agent_ = nullptr; //* identity void* identity_ = nullptr; //* ssh host QHostInfo sshHost_; //* connection attributes ConnectionAttributes attributes_; //* authentication methods QString authenticationMethods_; //* state StateMask state_ = Uninitialized; //* error string QString error_; //* command list using CommandList = QList; CommandList commands_; Command lastCommand_ = None; //* timer QBasicTimer timer_; //* latency int latency_ = 10; }; } Q_DECLARE_OPERATORS_FOR_FLAGS( Ssh::Connection::StateMask ); #endif Top-2.3.4/base-ssh/SshConnectionAttributes.h0000644000175000017500000001072413135553151017074 0ustar hlehle#ifndef SshConnectionAttributes_h #define SshConnectionAttributes_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshTunnelAttributes.h" #include "Counter.h" #include #include namespace Ssh { //_________________________________________________________ class ConnectionAttributes: private Base::Counter { public: //* used to drag and drop in models static const QString MimeType; using List = QList; using ListIterator = QListIterator; //* constructor explicit ConnectionAttributes(): Counter( "Ssh::ConnectionAttributes" ) {} virtual ~ConnectionAttributes() = default; //*@name accessors //@{ //* name const QString& name() const { return name_; } //* host const QString& host() const { return host_; } //* user name const QString& userName() const { return userName_; } //* password const QString& password() const { return password_; } //* true if password is to be remembered bool rememberPassword() const { return rememberPassword_; } //* true if auto connect bool autoConnect() const { return autoConnect_; } //* port int port() const { return port_; } //* tunnels TunnelAttributes::Set tunnels() const { return tunnels_; } //* validity bool isValid() const; //@} //*@name modifiers //@{ //* name void setName( const QString& name ) { name_ = name; } //* host void setHost( const QString& host ) { host_ = host; } //* user name void setUserName( const QString& userName ) { userName_ = userName; } //* password void setPassword( const QString& password ) { password_ = password; } //* remember password void setRememberPassword( bool value ) { rememberPassword_ = value; } //* set auto connect void setAutoConnect( bool value ) { autoConnect_ = value; } //* port void setPort( int port ) { port_ = port; } //* set tunnels void setTunnels( const TunnelAttributes::List ); //* add tunnel void addTunnel( const TunnelAttributes& ); //@} //* used to find attributes with same names class SameNameFTor { public: //* constructor explicit SameNameFTor( const QString& name ): name_( name ) {} //* predicate bool operator() (const ConnectionAttributes& other ) const { return other.name() == name_; } private: //* prediction const QString name_; }; private: //* connection name QString name_; //* host QString host_; //* user QString userName_; //* password QString password_; //* remember password bool rememberPassword_ = false; //* auto connect bool autoConnect_ = false; //* port int port_ = 22; //* tunnels TunnelAttributes::Set tunnels_; //* equal to operator friend bool operator == (const ConnectionAttributes&, const ConnectionAttributes&); }; //* less than operator inline bool operator < (const ConnectionAttributes& first, const ConnectionAttributes& second) { return first.name() < second.name(); } } #endif Top-2.3.4/base-ssh/SshSocket.h0000644000175000017500000000355413126214754014164 0ustar hlehle#ifndef SshSocket_h #define SshSocket_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshBaseSocket.h" #include #include #include #include #include namespace Ssh { //* ssh socket class Socket: public BaseSocket { Q_OBJECT public: //* constructor explicit Socket( QObject* ); //*@name modifiers //@{ //* connect to host void connectToHost( void*, const QString&, quint16 ); //* wait for connected /** warning, this method is blocking */ bool waitForConnected( int msecs = 30000 ); //@} protected: //* timer event void timerEvent( QTimerEvent* ); private: //* try connect channel, returns true on success bool _tryConnect(); //* session pointer void* session_ = nullptr; //* host QString host_; //* port quint16 port_ = 0; //* timer QBasicTimer timer_; }; } #endif Top-2.3.4/base-ssh/SshFileReadSocket.h0000644000175000017500000000460413126214754015555 0ustar hlehle#ifndef SshFileReadSocket_h #define SshFileReadSocket_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshBaseSocket.h" #include "TimeStamp.h" #include #include #include #include #include #include namespace Ssh { //* ssh socket class FileReadSocket: public BaseSocket { Q_OBJECT public: //* constructor explicit FileReadSocket( QObject* ); //*@name modifiers //@{ //* connect to remote void connectToFile( void*, const QString& ); //* wait for connected /** warning, this method is blocking */ bool waitForConnected( int msecs = 30000 ); //@} //*@name accessors //@{ //* file size qint64 fileSize() const { return isConnected() ? stat_.st_size:0; } //* access time TimeStamp accessTime() const { return isConnected() ? TimeStamp( stat_.st_atime ):TimeStamp(); } //* modification time TimeStamp modificationTime() const { return isConnected() ? TimeStamp( stat_.st_mtime ):TimeStamp(); } //@} protected: //* timer event void timerEvent( QTimerEvent* ); private: //* try connect channel, returns true on success bool _tryConnect(); //* session pointer void* session_ = nullptr; //* host QString path_; //* file information struct ::stat stat_; //* timer QBasicTimer timer_; }; } #endif Top-2.3.4/base-ssh/SshLoginDialog.cpp0000644000175000017500000000740213126214754015453 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "SshLoginDialog.h" #include "GridLayout.h" #include "QtUtil.h" #include namespace Ssh { //___________________________________________________________________________ LoginDialog::LoginDialog( QWidget* parent ): CustomDialog( parent, OkButton|CancelButton|Separator ) { Debug::Throw( "LoginDialog::LoginDialog.\n" ); setOptionName( "SSH_LOGIN_DIALOG" ); setWindowTitle( tr( "SSH login - Homechat" ) ); GridLayout* gridLayout = new GridLayout; gridLayout->setMargin(0); gridLayout->setMaxCount(2); gridLayout->setColumnAlignment( 0, Qt::AlignRight|Qt::AlignVCenter ); mainLayout().addLayout( gridLayout ); QLabel* label; // user name gridLayout->addWidget( label = new QLabel( tr( "User name:" ), this ) ); gridLayout->addWidget( userNameEditor_ = new LineEditor( this ) ); label->setBuddy( userNameEditor_ ); // password gridLayout->addWidget( label = new QLabel( tr( "Password:" ), this ) ); gridLayout->addWidget( passwordEditor_ = new LineEditor( this ) ); passwordEditor_->setEchoMode( QLineEdit::Password ); label->setBuddy( passwordEditor_ ); gridLayout->setColumnStretch( 1, 1 ); // remember password gridLayout->addWidget( rememberPaswordCheckBox_ = new QCheckBox( tr( "Remember password" ) ), gridLayout->currentRow(), 1, 1, 1 ); gridLayout->addWidget( showPasswordCheckBox_ = new QCheckBox( tr( "Show password" ) ), gridLayout->currentRow(), 1, 1, 1 ); connect( showPasswordCheckBox_, SIGNAL(toggled(bool)), SLOT(_toggleShowPassword(bool)) ); } //______________________________________________________________________ ConnectionAttributes LoginDialog::attributes() const { ConnectionAttributes attributes( attributes_ ); attributes.setUserName( userNameEditor_->text() ); attributes.setPassword( passwordEditor_->text() ); attributes.setRememberPassword( rememberPaswordCheckBox_->isChecked() ); return attributes; } //______________________________________________________________________ void LoginDialog::setAttributes( const ConnectionAttributes& attributes ) { attributes_ = attributes; if( !attributes.host().isEmpty() ) setWindowTitle( QString( tr( "SSH login into %1" ) ).arg( attributes.host() ) ); userNameEditor_->setText( attributes.userName() ); passwordEditor_->setText( attributes.password() ); rememberPaswordCheckBox_->setChecked( attributes.rememberPassword() ); if( attributes.userName().isEmpty() ) userNameEditor_->setFocus(); else passwordEditor_->setFocus(); } //______________________________________________________________________ void LoginDialog::_toggleShowPassword( bool value ) { passwordEditor_->setEchoMode( value ? QLineEdit::Normal:QLineEdit::Password); } } Top-2.3.4/Top.spec0000644000175000017500000000107013136571447012013 0ustar hlehle%define ver 2.3.4 %define rel 0 %define prefix /usr Summary: running processes control Name: Top Version: %{ver} Release: %{rel} License: GPL Group: User Interface/X Source: %{name}-%{ver}.tar.gz BuildRoot: /var/tmp/%{name}-buildroot %description running processes control %prep %setup -q -n %{name}-%{ver} %{rel} %build cmake -DCMAKE_INSTALL_PREFIX=%{prefix} . make -j4 %install rm -rf $RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc COPYING INSTALL %{prefix}/bin/Top %changelog Top-2.3.4/base/0000755000175000017500000000000013136572002011275 5ustar hlehleTop-2.3.4/base/CppUtil.h0000644000175000017500000000661013136400126013026 0ustar hlehle#ifndef CppUtil_h #define CppUtil_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include #if QT_VERSION >= 0x050100 #include #else #include #endif #include #include namespace Base { template using underlying_type_t = typename std::underlying_type::type; //* convert an strong type enum to integral type template constexpr typename std::underlying_type::type toIntegralType(T value) noexcept { return static_cast>(value);} #if QT_VERSION >= 0x050100 // for new Qt versoins, QHash can be constructed from initializer_list. So just move the arguments template std::initializer_list> makeT( std::initializer_list>&& reference ) noexcept { return std::move( reference ); } // for new Qt versoins, QMap can be constructed from initializer_list. So just move the arguments template std::initializer_list makeT( std::initializer_list&& reference ) noexcept { return std::move( reference ); } #else // for old QT versions there is no QHash constructor from initializer_list template T makeT( std::initializer_list>&& reference ) { T out; for( auto&& pair:reference ) { out.insert( pair.first, pair.second ); } return out; } // for old QT versions there is no QSet constructor from initializer_list template T makeT( std::initializer_list&& reference ) { T out; for( auto&& value:reference ) { out.insert( value ); } return out; } #endif } //* fancy qhash for all enum types template::value>::type> uint qHash( const T& value ) { return qHash(Base::toIntegralType(value)); } //* different from operator template bool operator != (const T& first, const U& second) { return !(first == second); } //* more than template bool operator > (const T& first, const U& second) { return second < first; } //* less or equal template bool operator <= (const T& first, const U& second) { return !(second < first); } //* more or equal template bool operator >= (const T& first, const U& second) { return !(first < second); } #endif Top-2.3.4/base/Singleton.h0000644000175000017500000000416013132461101013402 0ustar hlehle#ifndef Singleton_h #define Singleton_h /****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Counter.h" #include "NonCopyable.h" #include namespace Base{ //* a class singleton used to centralize all objects that need static creation class Singleton final: private Counter, private NonCopyable { public: //* return singleton static Singleton& get(); //*@name accessors //@{ //* true if has application bool hasApplication() const { return (bool) application_; } //* application QObject* application() { Q_CHECK_PTR( application_ ); return application_; } //* cast template< typename T > T* application() { Q_CHECK_PTR( application_ ); return static_cast( application_ ); } //@} //*@name modifiers //@{ //* set application void setApplication( QObject* application ) { Q_ASSERT( !application_ ); application_ = application; } //@} private: //* constructor explicit Singleton(): Counter( "Singleton" ) {} QObject* application_ = nullptr; }; } #endif Top-2.3.4/base/Option.cpp0000644000175000017500000000621113126214754013257 0ustar hlehle/****************************************************************************** * * Copyright (C) 2002 Hugo PEREIRA * * This 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 2 of the License, or (at your option) any later * version. * * This software 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 * this program. If not, see . * *******************************************************************************/ #include "Option.h" //________________________________________________________ QTextStream& operator >> ( QTextStream& in, bool& value ) { int local; in >> local; value = (bool)( local ); return in; } //________________________________________________________ Option::Option(): Counter( "Option" ) {} //________________________________________________________ Option::Option( const char* value, Flags flags ): Counter( "Option" ), flags_( flags ) { value_ = value; } //________________________________________________________ Option::Option( const QByteArray& value, Flags flags ): Counter( "Option" ), value_( value ), flags_( flags ) {} //________________________________________________________ Option::Option( const QString& value, Flags flags ): Counter( "Option" ), value_( value.toUtf8() ), flags_( flags ) {} //________________________________________________________ QDataStream &operator << ( QDataStream &stream, const Option& option ) { static const quint32 version = 0; stream << version << option.value_ << option.defaultValue_ << quint32(option.flags_) << quint32(option.defaultFlags_); return stream; } //________________________________________________________ QDataStream &operator >> ( QDataStream &stream, Option& option ) { quint32 version; stream >> version; if( version == 0 ) { quint32 flags; quint32 defaultFlags; stream >> option.value_ >> option.defaultValue_ >> flags >> defaultFlags; option.flags_ = Option::Flags( flags ); option.defaultFlags_ = Option::Flags( defaultFlags ); } else Debug::Throw(0) << "Unrecognized Option version: " << version << endl; return stream; } //________________________________________________________ QTextStream &operator << ( QTextStream &out, const Option& option ) { if( !option.isSet() ) out << "not set"; else out << option.raw(); out << QString( " (0b%1)" ).arg( QString::number( option.flags_, 2 ) ); return out; } //________________________________________________________ QTextStream &operator << ( QTextStream &out, const QList