1 /*===========================================================================
2 *
3 *                            PUBLIC DOMAIN NOTICE
4 *               National Center for Biotechnology Information
5 *
6 *  This software/database is a "United States Government Work" under the
7 *  terms of the United States Copyright Act.  It was written as part of
8 *  the author's official duties as a United States Government employee and
9 *  thus cannot be copyrighted.  This software/database is freely available
10 *  to the public for use. The National Library of Medicine and the U.S.
11 *  Government have not placed any restriction on its use or reproduction.
12 *
13 *  Although all reasonable efforts have been taken to ensure the accuracy
14 *  and reliability of the software and data, the NLM and the U.S.
15 *  Government do not and cannot warrant the performance or results that
16 *  may be obtained by using this software or data. The NLM and the U.S.
17 *  Government disclaim all warranties, express or implied, including
18 *  warranties of performance, merchantability or fitness for any particular
19 *  purpose.
20 *
21 *  Please cite the author in any work or product based on this material.
22 *
23 * ===========================================================================
24 *
25 */
26 
27 #include "sraconfigview.h"
28 #include "sraconfigmodel.h"
29 #include "../vdb-config/configure.h"
30 #include "../vdb-config/interactive.h"
31 #include "../vdb-config/vdb-config-model.hpp"
32 //#include "../sra-tools-gui/interfaces/ktoolbaritem.h"
33 
34 #include <klib/rc.h>
35 #include <kfg/config.h>
36 #include <kfg/properties.h>
37 #include <kfg/repository.h>
38 #include <kfg/ngc.h>
39 #include <kfs/directory.h>
40 #include <kfs/file.h>
41 
42 #include <QAction>
43 #include <QBoxLayout>
44 #include <QButtonGroup>
45 #include <QCloseEvent>
46 #include <QCheckBox>
47 #include <QComboBox>
48 #include <QFileDialog>
49 #include <QGridLayout>
50 #include <QGroupBox>
51 #include <QInputDialog>
52 #include <QLabel>
53 #include <QMenu>
54 #include <QMenuBar>
55 #include <QMessageBox>
56 #include <QPushButton>
57 #include <QScrollArea>
58 #include <QToolBar>
59 
60 #include <QDebug>
61 
62 extern "C"
63 {
run_interactive(vdbconf_model & m)64     rc_t run_interactive ( vdbconf_model &m )
65     {
66         (void) m;
67         return 0;
68     }
69 }
70 
71 struct WorkspaceItem
72 {
WorkspaceItemWorkspaceItem73     WorkspaceItem ( QString name, QString path, uint32_t id )
74         : name_label ( new QLabel ( name ) )
75         , path_label ( new QLabel ( path ) )
76         , edit_button ( new QPushButton ( "Edit" ) )
77         , ngc_id ( id )
78     {
79         name_label -> setObjectName ( "workspace_name_label");
80         name_label -> setFixedWidth ( 150 );
81         name_label -> setAlignment ( Qt::AlignRight );
82 
83         path_label -> setObjectName ( "workspace_path_label");
84         path_label -> setFrameShape ( QFrame::Panel );
85         path_label -> setFrameShadow ( QFrame::Sunken );
86 
87         edit_button -> setObjectName ( "workspace_edit_button" );
88         edit_button -> setFixedSize ( 30, 20 );
89     }
90 
WorkspaceItemWorkspaceItem91     WorkspaceItem ()
92         : name_label ( nullptr )
93         , path_label ( nullptr )
94         , edit_button ( nullptr )
95         , ngc_id ( -1 )
96     {}
97 
98     QLabel *name_label;
99     QLabel *path_label;
100     QPushButton *edit_button;
101 
102     int ngc_id;
103 };
104 
105 
106 /* static functions */
107 static
location_error(RootState state,QWidget * w)108 bool location_error ( RootState state, QWidget *w )
109 {
110     QString msg;
111 
112     switch ( state )
113     {
114     case RootState_NotChanged       : return true;
115     case RootState_NotUnique        : msg = QString ( "location not unique, select a different one" ); break;
116     case RootState_MkdirFail        : msg = QString ( "could not created directory, maybe permisson problem" ); break;
117     case RootState_NewPathEmpty     : msg = QString ( "you gave me an empty path" ); break;
118     case RootState_NewDirNotEmpty   : msg = QString ( "the given location is not empty" ); break;
119     case RootState_NewNotDir        : msg = QString ( "new location is not a directory" ); break;
120     case RootState_Error            : msg = QString ( "error changing location" ); break;
121     default                             : msg = QString ( "unknown enum" ); break;
122     }
123 
124     QMessageBox::critical ( w
125                             , "Error"
126                             , msg
127                             , QMessageBox::Ok );
128     return false;
129 }
130 
131 static
public_location_start_dir(SRAConfigModel * model)132 std :: string public_location_start_dir ( SRAConfigModel *model )
133 {
134     std :: string s = model -> get_public_path ();
135 
136     if ( ! model -> path_exists ( s ) )
137         s = model -> get_user_default_path ();
138 
139     if ( ! model -> path_exists ( s ) )
140         s = model -> get_home_path () + "/ncbi";
141 
142     if ( ! model -> path_exists ( s ) )
143         s = model -> get_home_path ();
144 
145     if ( ! model -> path_exists ( s ) )
146         s = model -> get_current_path ();
147 
148     return s;
149 }
150 
151 static
select_public_location(SRAConfigModel * model,QWidget * w)152 bool select_public_location ( SRAConfigModel *model, QWidget *w )
153 {
154     std ::string path = public_location_start_dir ( model ) . c_str ();
155 
156     if ( model -> path_exists ( path ) )
157     {
158         QString p = QFileDialog :: getOpenFileName ( w
159                                                 , "Import Workspace"
160                                                 , path . c_str () );
161         path = p . toStdString ();
162     }
163     else
164     {
165         QString p = QInputDialog::getText ( w
166                                        , ""
167                                        , "Location of public cache"
168                                        , QLineEdit::Normal );
169         path = p . toStdString ();
170     }
171 
172     if ( path . length () > 0 )
173     {
174         QString p = path . c_str ();
175         QMessageBox::StandardButton reply;
176         reply = QMessageBox::question ( w
177                                         , ""
178                                         , "Change the location to '" + p + "'?"
179                                         , QMessageBox::Yes | QMessageBox::No );
180         if ( reply == QMessageBox::Yes )
181         {
182             bool flush_old = false;
183             bool reuse_new = false;
184 
185             RootState state = model -> set_public_path ( path, flush_old, reuse_new );
186 
187             switch ( state )
188             {
189             case RootState_OK:
190                 return true;
191             case RootState_OldNotEmpty:
192             {
193                 QMessageBox::StandardButton reply;
194                 reply = QMessageBox::question ( w
195                                                 , "Directory not empty"
196                                                 , "Previous location is not empty, flush it?"
197                                                 , QMessageBox::Yes | QMessageBox::No );
198                 if ( reply == QMessageBox::Yes )
199                 {
200                     flush_old = true;
201                     state = model -> set_public_path ( path, flush_old, reuse_new );
202                     if ( state == RootState_OK )
203                         return true;
204                     else
205                         return location_error ( state, w );
206         }
207             }
208             default:
209                 return location_error ( state, w );
210             }
211         }
212     }
213 
214     return false;
215 }
216 
217 static
protected_location_start_dir(SRAConfigModel * model,uint32_t id)218 std :: string protected_location_start_dir ( SRAConfigModel *model, uint32_t id )
219 {
220     std :: string s = model -> get_workspace_path ( id );
221 
222     if ( ! model -> path_exists ( s ) )
223         s = model -> get_user_default_path ();
224 
225     if ( ! model -> path_exists ( s ) )
226         s = model -> get_home_path () + "/ncbi";
227 
228     if ( ! model -> path_exists ( s ) )
229         s = model -> get_home_path ();
230 
231     if ( ! model -> path_exists ( s ) )
232         s = model -> get_current_path ();
233 
234     return s;
235 }
236 
237 static
select_protected_location(SRAConfigModel * model,int id,QWidget * w)238 bool select_protected_location ( SRAConfigModel *model, int id, QWidget *w )
239 {
240     std :: string path = protected_location_start_dir ( model, id );
241     qDebug () << "Protect location path: " << QString ( path . c_str () ) << " [" << id << "]";
242 
243     if ( model -> path_exists ( path ) )
244     {
245         QString p = QFileDialog :: getOpenFileName ( w
246                                                 , "Import Workspace"
247                                                 , path . c_str () );
248         path = p . toStdString ();
249     }
250     else
251     {
252         QString p = QInputDialog::getText ( w
253                                        , ""
254                                        , "Location of dbGaP project"
255                                        , QLineEdit::Normal );
256         path = p . toStdString ();
257     }
258 
259     if ( path . length () > 0 )
260     {
261         QString repo_name = model -> get_workspace_name ( id ) . c_str ();
262         QMessageBox::StandardButton reply;
263         reply = QMessageBox::question ( w
264                                         , ""
265                                         , "Change the location of '" + repo_name + "' to '" + QString ( path . c_str () ) + "'?"
266                                         , QMessageBox::Yes | QMessageBox::No );
267         if ( reply == QMessageBox::Yes )
268         {
269             bool flush_old = false;
270             bool reuse_new = false;
271 
272             RootState state = model -> set_workspace_path ( path, id, flush_old, reuse_new );
273 
274             switch ( state )
275             {
276             case RootState_OK:
277                 return true;
278             case RootState_OldNotEmpty:
279             {
280                 QMessageBox::StandardButton reply;
281                 reply = QMessageBox::question ( w
282                                                 , "Directory not empty"
283                                                 , "Previous location is not empty, flush it?"
284                                                 , QMessageBox::Yes | QMessageBox::No );
285                 if ( reply == QMessageBox::Yes )
286                 {
287                     flush_old = true;
288                     state = model -> set_workspace_path ( path, id, flush_old, reuse_new );
289                     if ( state == RootState_OK )
290                         return true;
291                     else
292                         return location_error ( state, w );
293                 }
294             }
295             default:
296                 return location_error ( state, w );
297             }
298         }
299     }
300 
301     return false;
302 }
303 
304 static
make_ngc_obj(const KNgcObj ** ngc,std::string & path)305 bool make_ngc_obj ( const KNgcObj ** ngc, std::string &path )
306 {
307     KDirectory * dir;
308     rc_t rc = KDirectoryNativeDir( &dir );
309     if ( rc == 0 )
310     {
311         const KFile * src;
312         rc = KDirectoryOpenFileRead ( dir, &src, "%s", path.c_str() );
313         if ( rc == 0 )
314         {
315             rc = KNgcObjMakeFromFile ( ngc, src );
316             KFileRelease( src );
317         }
318         KDirectoryRelease( dir );
319     }
320 
321     return ( rc == 0 );
322 }
323 
324 static
prepare_ngc(SRAConfigModel * model,const KNgcObj * ngc,QString * loc,QWidget * w)325 bool prepare_ngc ( SRAConfigModel *model, const KNgcObj *ngc, QString *loc, QWidget *w )
326 {
327     std :: string base_path = model -> get_user_default_path ();
328     std :: string path = model -> get_ngc_root ( base_path, ngc );
329 
330     RootState state = model -> configure_workspace ( path );
331 
332     switch ( state )
333     {
334     case RootState_OK:
335     {
336         *loc = path . c_str ();
337         return true;
338     }
339     case RootState_OldNotEmpty:
340     {
341         QMessageBox::StandardButton reply;
342         reply = QMessageBox::question ( w
343                                         , "Directory not empty"
344                                         , "Workspace location is not empty. Use it anyway?"
345                                         , QMessageBox::Yes | QMessageBox::No );
346         if ( reply == QMessageBox::Yes )
347         {
348             state = model -> configure_workspace ( path, true );
349             if ( state == RootState_OK )
350             {
351                 *loc = path . c_str ();
352                 return true;
353             }
354             else
355                 return location_error ( state, w );
356         }
357     }
358     default:
359         return location_error ( state, w );
360     }
361 
362     return false;
363 }
364 
365 static
import_ngc(SRAConfigModel * model,std::string file,uint32_t & ngc_id,QWidget * w)366 bool import_ngc ( SRAConfigModel *model, std :: string file, uint32_t &ngc_id, QWidget *w )
367 {
368    const KNgcObj *ngc;
369    if ( ! make_ngc_obj ( &ngc, file ) )
370    {
371        QMessageBox::information ( w
372                                   , "Import Error"
373                                   , "Unable to import NGC file" );
374    }
375    else
376    {
377        QString path;
378        if ( ! prepare_ngc ( model, ngc, &path, w ) )
379            qDebug () << "failed to prepare ngc object";
380        else
381        {
382            qDebug () << "prepared ngc object";
383 
384            uint32_t result_flags = 0;
385 
386            if ( model -> import_ngc ( path . toStdString (), ngc, INP_CREATE_REPOSITORY, &result_flags ) )
387            {
388                /* we have it imported or it exists and no changes made */
389                bool modified = false;
390                if ( result_flags & INP_CREATE_REPOSITORY )
391                {
392                    /* success is the most common outcome, the repository was created */
393                    QMessageBox::information ( w
394                                               , "Import Successful"
395                                               , "project successfully imported" );
396 
397                    modified = true;
398                }
399                else
400                {
401                    /* repository did exist and is completely identical to the given ngc-obj */
402                    QMessageBox::information ( w
403                                               , ""
404                                               , "this project exists already, no changes made" );
405 
406                    modified = false;
407                }
408 
409                if ( model -> get_ngc_obj_id ( ngc, &ngc_id ) )
410                {
411                    qDebug () << "NGC ID: " << ngc_id;
412 
413                    QMessageBox::StandardButton reply;
414                    reply = QMessageBox::question ( w
415                                                    , ""
416                                                    , "Do you want to change the location?"
417                                                    , QMessageBox::Yes | QMessageBox::No );
418                    if ( reply == QMessageBox::Yes )
419                    {
420                        modified |= select_protected_location ( model, ngc_id, w );
421                    }
422                }
423                else
424                {
425                    QMessageBox::information ( w
426                                               , ""
427                                               , "Cannot find the imported Workspace" );
428                }
429 
430                if ( modified )
431                {
432                    model -> commit (); // TBD - on import of NGC files, do we automaically commit, or allow for revert and require apply button?
433                    model -> create_directory ( ngc );
434                    return true;
435                }
436            }
437            else if ( result_flags == 0 )
438            {
439                QMessageBox::critical ( w
440                                        , "Error"
441                                        , "Internal Error: Failed to impport the ngc-object"
442                                        , QMessageBox::Ok );
443            }
444            else
445            {
446                QMessageBox::information ( w, "", "the repository does already exist!" );
447 
448                if ( result_flags & INP_UPDATE_ENC_KEY )
449                {
450                    QMessageBox::StandardButton reply;
451                    reply = QMessageBox::question ( w
452                                                    , ""
453                                                    , "Encryption key would change, continue?"
454                                                    , QMessageBox::Yes | QMessageBox::No );
455                    if ( reply == QMessageBox::Yes  && ( result_flags & INP_UPDATE_DNLD_TICKET ) )
456                    {
457                        QMessageBox::StandardButton reply;
458                        reply = QMessageBox::question ( w
459                                                        , ""
460                                                        , "Download ticket would change, continue?"
461                                                        , QMessageBox::Yes | QMessageBox::No );
462                        if ( reply == QMessageBox::Yes  && ( result_flags & INP_UPDATE_DESC ) )
463                        {
464                            QMessageBox::StandardButton reply;
465                            reply = QMessageBox::question ( w
466                                                            , ""
467                                                            , "Description would change, continue?"
468                                                            , QMessageBox::Yes | QMessageBox::No );
469                            if ( reply == QMessageBox::Yes )
470                            {
471                                uint32_t result_flags2 = 0;
472                                if ( model -> import_ngc ( path . toStdString () , ngc, result_flags, &result_flags2 ) )
473                                {
474                                    QMessageBox::StandardButton reply;
475                                    reply = QMessageBox::question ( w
476                                                                    , ""
477                                                                    , "Project successfully updated!\nDo you want to change the location? "
478                                                                    , QMessageBox::Yes | QMessageBox::No );
479 
480                                    if ( reply == QMessageBox::Yes )
481                                    {
482                                        /* we have to find out the id of the imported/existing repository */
483                                        if ( model -> get_ngc_obj_id ( ngc, &ngc_id ) )
484                                        {
485                                            qDebug () << "NGC ID: " << ngc_id;
486                                            select_protected_location ( model, ngc_id, w );
487                                        }
488                                        else
489                                            QMessageBox::information ( w, "", "the repository does already exist!" );
490                                    }
491 
492                                    model -> commit ();
493 
494                                    return true;
495                                }
496                                else
497                                {
498                                    QMessageBox::critical ( w
499                                                            , "Error"
500                                                            , "Internal Error: Failed to impport the ngc-object"
501                                                            , QMessageBox::Ok );
502                                }
503                            }
504                            else
505                                QMessageBox::information ( w, "", "The import was canceled" );
506                        }
507                    }
508                }
509            }
510        }
511 
512        KNgcObjRelease ( ngc );
513    }
514 
515     return false;
516 }
517 
518 
519 
520 /* Class methods */
521 
SRAConfigView(QWidget * parent)522 SRAConfigView :: SRAConfigView ( QWidget *parent )
523     : QWidget ( parent )
524     , model ( new SRAConfigModel ( configure_model (), this ) )
525     , main_layout ( new QVBoxLayout () )
526 {
527     setObjectName ( "config_view" );
528     connect ( this, SIGNAL ( dirty_config () ), this, SLOT ( modified_config () ) );
529 
530     main_layout -> setAlignment ( Qt::AlignTop );
531     main_layout -> setMargin ( 0 );
532     main_layout -> setSpacing ( 0 );
533 
534     main_layout -> addWidget ( setup_workflow_group () );
535     main_layout -> addWidget ( setup_option_group () );
536 
537     setLayout ( main_layout );
538 
539     load_settings ();
540 
541     show ();
542 }
543 
~SRAConfigView()544 SRAConfigView :: ~SRAConfigView ()
545 {
546 
547 }
548 
load_settings()549 void SRAConfigView :: load_settings ()
550 {
551     if ( ! model -> remote_enabled () )
552         bg_remote_access -> button ( 0 ) -> setChecked ( true );
553      else
554         bg_remote_access -> button ( 1 ) -> setChecked ( true );
555 
556     if ( ! model -> global_cache_enabled () )
557         bg_local_caching -> button ( 0 ) -> setChecked ( true );
558      else
559         bg_local_caching -> button ( 1 ) -> setChecked ( true );
560 
561     if ( model -> site_workspace_exists () ) // TBD - Possible bug
562     {
563         if ( ! model -> site_enabled () )
564             bg_use_site -> button ( 0 ) -> setChecked ( true );
565         else
566             bg_use_site -> button ( 1 ) -> setChecked ( true );
567     }
568     else
569     {
570         bg_use_site -> button ( 0 ) -> setDisabled ( true );
571         bg_use_site -> button ( 1 ) -> setDisabled ( true );
572     }
573 
574     if ( ! model -> proxy_enabled () )
575     {
576         bg_use_proxy -> button ( 0 ) -> setChecked ( true );
577         proxyEditor -> setDisabled ( true );
578     }
579      else
580     {
581         bg_use_proxy -> button ( 1 ) -> setChecked ( true );
582         proxyEditor -> setText ( QString ( model -> get_proxy_path () . c_str () ) );
583     }
584 
585     if ( ! model -> allow_all_certs () )
586         bg_allow_all_certs -> button ( 0 ) -> setChecked ( true );
587      else
588         bg_allow_all_certs -> button ( 1 ) -> setChecked ( true );
589 }
590 
setup_workflow_group()591 QWidget * SRAConfigView::setup_workflow_group ()
592 {
593 
594     QWidget *widget = new QWidget ();
595     widget -> setObjectName ( "workflow_widget" );
596     widget -> setFixedHeight ( 70 );
597 
598     QHBoxLayout *layout = new QHBoxLayout ();
599     layout -> setAlignment ( Qt::AlignBottom | Qt::AlignRight );
600     layout -> setSpacing ( 5 );
601 
602     apply_btn = new QPushButton ( "Apply" );
603     apply_btn -> setDisabled ( true );
604     connect ( apply_btn, SIGNAL ( clicked () ), this, SLOT ( commit_config  () ) );
605 
606     discard_btn = new QPushButton ( "Revert" );
607     discard_btn -> setDisabled ( true );
608     connect ( discard_btn, SIGNAL ( clicked () ), this, SLOT ( reload_config () ) );
609 
610     layout -> addWidget ( discard_btn );
611     layout -> addWidget ( apply_btn );
612 
613     widget -> setLayout ( layout );
614 
615     return widget;
616 }
617 
618 static
make_no_yes_button_group(QPushButton ** p_no,QPushButton ** p_yes)619 QButtonGroup * make_no_yes_button_group ( QPushButton **p_no, QPushButton **p_yes )
620 {
621     QButtonGroup *group = new QButtonGroup ();
622 
623     QPushButton *no = new QPushButton ( "No" );
624     no -> setObjectName ( "button_no" );
625     no -> setCheckable ( true );
626     no -> setFixedSize ( 60, 40 );
627 
628     QPushButton *yes = new QPushButton ( "Yes" );
629     yes -> setObjectName ( "button_yes" );
630     yes -> setCheckable ( true );
631     yes -> setFixedSize ( 60, 40 );
632 
633     group -> addButton ( no, 0 );
634     group -> addButton ( yes, 1 );
635 
636     *p_no = no;
637     *p_yes = yes;
638 
639     return group;
640 }
641 
642 static
make_button_option_row(QString name,QString desc,QPushButton * b1,QPushButton * b2)643 QWidget * make_button_option_row ( QString name, QString desc,
644                                    QPushButton *b1, QPushButton *b2 )
645 {
646     QWidget *row = new QWidget ();
647     row -> setObjectName ( "row_widget" );
648 
649     QLabel *name_l = new QLabel ( name );
650     name_l -> setObjectName ( "name_label" );
651     name_l -> setFixedHeight ( 40 );
652 
653     QLabel *desc_l = new QLabel ( desc );
654     desc_l -> setObjectName ( "desc_label" );
655     desc_l -> setFixedWidth ( ( row -> size () . width () ) );
656     desc_l -> setWordWrap ( true );
657 
658     QHBoxLayout *row_h_layout = new QHBoxLayout ();
659     row_h_layout -> setSpacing ( 10 );
660     row_h_layout -> addWidget ( name_l );
661     row_h_layout -> setAlignment ( name_l, Qt::AlignLeft );
662     row_h_layout -> addWidget ( b1 );
663     row_h_layout -> setAlignment ( b1, Qt::AlignRight );
664     row_h_layout -> addWidget ( b2 );
665 
666     QVBoxLayout *row_v_layout = new QVBoxLayout ();
667     row_v_layout -> setSpacing ( 5 );
668     row_v_layout -> addLayout ( row_h_layout );
669     row_v_layout -> addWidget ( desc_l, 0, Qt::AlignLeft );
670 
671     row -> setLayout ( row_v_layout );
672 
673     return row;
674 }
675 
676 static
make_editor_button_option_row(QString name,QString desc,QLineEdit * editor,QPushButton * b1,QPushButton * b2)677 QWidget * make_editor_button_option_row ( QString name, QString desc, QLineEdit *editor,
678                                           QPushButton *b1, QPushButton *b2 )
679 {
680     QWidget *row = new QWidget ();
681     row -> setObjectName ( "row_widget" );
682 
683     QLabel *name_l = new QLabel ( name );
684     name_l -> setObjectName ( "name_label" );
685     name_l -> setFixedHeight ( 40 );
686 
687     QLabel *desc_l = new QLabel ( desc );
688     desc_l -> setObjectName ( "desc_label" );
689     desc_l -> setFixedWidth ( ( row -> size () . width () ) );
690     desc_l -> setWordWrap ( true );
691 
692 
693     editor -> setFocusPolicy ( Qt::FocusPolicy::ClickFocus );
694     editor -> setFixedHeight ( 40 );
695     editor -> setAlignment ( Qt::AlignCenter );
696 
697     QHBoxLayout *row_h_layout = new QHBoxLayout ();
698     row_h_layout -> setSpacing ( 10 );
699     row_h_layout -> addWidget ( name_l );
700     row_h_layout -> setAlignment ( name_l, Qt::AlignLeft );
701     row_h_layout -> addWidget ( editor );
702     row_h_layout -> setAlignment ( editor, Qt::AlignRight );
703     row_h_layout -> addWidget ( b1 );
704     row_h_layout -> addWidget ( b2 );
705 
706     QVBoxLayout *row_v_layout = new QVBoxLayout ();
707     row_v_layout -> setSpacing ( 5 );
708     row_v_layout -> addLayout ( row_h_layout );
709     row_v_layout -> addWidget ( desc_l, 0, Qt::AlignLeft );
710 
711     row -> setLayout ( row_v_layout );
712 
713     return row;
714 }
715 
setup_general_settings()716 void SRAConfigView::setup_general_settings ()
717 {
718     QLabel *label = new QLabel ( "General Settings" );
719     QPushButton *no = nullptr;
720     QPushButton *yes = nullptr;
721     QString name;
722     QString desc;
723 
724     scrollWidgetLayout -> addWidget ( label );
725     scrollWidgetLayout -> addSpacing ( 5 );
726 
727     // row 1
728     name = QString ("Enable Remote Access");
729     desc = QString ("Connect to NCBI over http or https. Connect to NCBI over http or https."
730                             "Connect to NCBI over http or https.Connect to NCBI over http or https."
731                             "Connect to NCBI over http or https.Connect to NCBI over http or https.");
732     connect ( bg_remote_access = make_no_yes_button_group ( &no, &yes ),
733               SIGNAL ( buttonClicked ( int ) ), this, SLOT ( toggle_remote_enabled ( int ) ) );
734 
735     scrollWidgetLayout -> addWidget ( make_button_option_row ( name, desc, no, yes ) );
736     // row 1
737 
738     // row 2
739     name = QString ("Enable Local File Caching");
740     connect ( bg_local_caching = make_no_yes_button_group ( &no, &yes ),
741               SIGNAL ( buttonClicked ( int ) ), this, SLOT ( toggle_local_caching ( int ) ) );
742 
743     scrollWidgetLayout -> addWidget ( make_button_option_row ( name, desc, no, yes ) );
744     // row 2
745 }
746 
setup_network_setting()747 void SRAConfigView::setup_network_setting ()
748 {
749     QLabel *label = new QLabel ( "Network Settings" );
750     QPushButton *no = nullptr;
751     QPushButton *yes = nullptr;
752     QString name;
753     QString desc;
754 
755     scrollWidgetLayout -> addWidget ( label );
756     scrollWidgetLayout -> addSpacing ( 5 );
757 
758     // row 1
759     name = QString ("Use Site Installation") ;
760     desc = QString ("Connect to NCBI over http or https. Connect to NCBI over http or https."
761                             "Connect to NCBI over http or https.Connect to NCBI over http or https."
762                             "Connect to NCBI over http or https.Connect to NCBI over http or https.");
763 
764     connect ( bg_use_site = make_no_yes_button_group ( &no, &yes ),
765               SIGNAL ( buttonClicked ( int ) ), this, SLOT ( toggle_use_site ( int ) ) );
766 
767     scrollWidgetLayout -> addWidget ( make_button_option_row ( name, desc, no, yes ) );
768     // row 1
769 
770     // row 2
771     proxyEditor = new QLineEdit ();
772     proxyEditor -> setPlaceholderText ( "xxx.xxx.xxx.xxx" );
773     connect ( proxyEditor, SIGNAL ( editingFinished () ), this, SLOT ( edit_proxy_path () ) );
774 
775     name = QString ("Use Proxy");
776     connect ( bg_use_proxy = make_no_yes_button_group ( &no, &yes ),
777               SIGNAL ( buttonClicked ( int ) ), this, SLOT ( toggle_use_proxy ( int ) ) );
778 
779     scrollWidgetLayout -> addWidget ( make_editor_button_option_row ( name, desc, proxyEditor,
780                                                           no, yes ) );
781 
782     // row 2
783 
784     //row 3
785     connect ( bg_allow_all_certs = make_no_yes_button_group ( &no, &yes ),
786               SIGNAL ( buttonClicked ( int ) ), this, SLOT ( toggle_allow_all_certs ( int ) ) );
787 
788     name = QString ( "Allow All Certificates" );
789 
790     scrollWidgetLayout -> addWidget ( make_button_option_row ( name, desc, no, yes) );
791     // row 3
792 }
793 
setup_option_group()794 QWidget * SRAConfigView::setup_option_group ()
795 {
796     scrollWidgetLayout = new QVBoxLayout ();
797     scrollWidgetLayout -> setAlignment ( Qt::AlignTop );
798     scrollWidgetLayout -> setSpacing ( 0 );
799 
800     setup_general_settings ();
801     scrollWidgetLayout -> addSpacing ( 20 );
802     setup_network_setting ();
803 
804     QWidget *scrollWidget = new QWidget ();
805     scrollWidget -> setObjectName ("scroll_widget");
806     scrollWidget -> setLayout ( scrollWidgetLayout );
807     scrollWidget -> setSizePolicy ( QSizePolicy::Ignored, QSizePolicy::Ignored);
808 
809     QScrollArea *scrollArea = new QScrollArea ();
810     scrollArea -> setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOff );
811     scrollArea -> setWidget ( scrollWidget );
812     scrollArea -> setWidgetResizable ( true );
813 
814     return scrollArea;
815 }
816 
closeEvent(QCloseEvent * ev)817 void SRAConfigView :: closeEvent ( QCloseEvent *ev )
818 {
819 #if ALLOW_SLOTS
820     if ( model -> config_changed () )
821     {
822         QMessageBox::StandardButton reply;
823         reply = QMessageBox::question ( this
824                                         , ""
825                                         , "Save changes? "
826                                         , QMessageBox::No | QMessageBox::Yes );
827 
828         if ( reply == QMessageBox::Yes )
829             commit_config ();
830     }
831 
832     ev -> accept ();
833 #endif
834 }
835 
add_workspace(QString name,QString val,int ngc_id,bool insert)836 void SRAConfigView :: add_workspace (QString name, QString val, int ngc_id, bool insert )
837 {
838     QHBoxLayout *layout = new QHBoxLayout ();
839 
840     WorkspaceItem *ws = new WorkspaceItem ( name . append ( ':' ), val, ngc_id );
841 
842     if ( ngc_id == -1 )
843     {
844         public_workspace = ws;
845         connect ( ws -> edit_button, SIGNAL ( clicked () ), this, SLOT ( edit_public_path () ) );
846     }
847     else
848     {
849         protected_workspaces . append ( ws );
850         connect ( ws -> edit_button, SIGNAL ( clicked () ), this, SLOT ( edit_workspace_path () ) );
851     }
852 
853     layout -> addWidget ( ws -> name_label );
854     layout -> addWidget ( ws -> path_label );
855     layout -> addWidget ( ws -> edit_button );
856 
857     if ( insert )
858     {
859         workspace_layout -> insertLayout ( workspace_layout -> count () - 1, layout );
860     }
861     else
862         workspace_layout -> addLayout ( layout );
863 }
864 
865 /*
866 void SRAConfigView :: import_workspace ()
867 {
868     // open a file dialog to browse for the repository
869     std :: string path = model -> get_home_path ();
870     if ( ! model -> path_exists ( path ) )
871         path = model -> get_current_path ();
872 
873     QString filter = tr ("NGS (*.ngc)" );
874     QString file = QFileDialog :: getOpenFileName ( this
875                                                     , "Import Workspace"
876                                                     , path . c_str ()
877                                                     , tr ( "NGC files (*.ngc)" ) );
878 
879     if ( ! file . isEmpty () )
880     {
881         std :: string s = file . toStdString ();
882         uint32_t ngc_id;
883         if ( import_ngc ( model, s, ngc_id, this ) )
884         {
885             QString name = model -> get_workspace_name ( ngc_id ) . c_str ();
886 
887             name = QInputDialog::getText ( this
888                                                    , tr ( "Name Workspace" )
889                                                    , tr ( "Choose a name for your workspace" )
890                                                    , QLineEdit::Normal
891                                                    , name );
892 
893             if ( name . isEmpty () )
894                 name = model -> get_workspace_name ( ngc_id ) . c_str ();
895 
896             add_workspace ( name, file, ngc_id, true );
897         }
898     }
899 }
900 
901 
902 QGroupBox * SRAConfigView :: setup_workspace_group ()
903 {
904     QGroupBox *group = new QGroupBox ();
905     group -> setObjectName ( "config_options_group" );
906 
907     workspace_layout = new QVBoxLayout ();
908     workspace_layout -> setAlignment ( Qt :: AlignTop );
909     workspace_layout -> setSpacing ( 15 );
910 
911     add_workspace ( "Public", model -> get_public_path () . c_str(), -1 );
912 
913     int ws_count = model -> workspace_count ();
914     qDebug () << "Setup workspace group: repo-count: " << ws_count;
915     for ( int i = 0; i < ws_count; ++ i )
916     {
917         std :: string name = model -> get_workspace_name ( i );
918         add_workspace ( name . c_str () ,
919                         model -> get_workspace_path ( i ) . c_str (),
920                         model -> get_workspace_id ( name ) );
921     }
922 
923     //3
924     QHBoxLayout *i_layout = new QHBoxLayout ();
925 
926     i_layout -> addSpacing ( 125 );
927 
928     QPushButton *import = new QPushButton ( "+" );
929     import -> setFixedSize ( 30, 25 );
930     connect ( import, SIGNAL ( clicked () ), this, SLOT ( import_workspace () ) );
931     i_layout -> addWidget ( import );
932 
933     i_layout -> addSpacing ( 5 );
934 
935     QLabel *label = new QLabel ();
936     label -> setFrameShape ( QFrame::Panel );
937     label -> setFrameShadow ( QFrame::Sunken );
938 
939     i_layout -> addWidget ( label );
940 
941     workspace_layout -> addLayout ( i_layout );
942 
943     //group -> setLayout ( workspace_layout );
944 
945     return group;
946 }
947 */
948 
949 
950 /*
951 void SRAConfigView :: advanced_settings ()
952 {
953     adv_setting_window = new QFrame ();
954     adv_setting_window -> resize ( this -> width () * .7, this -> height () / 2 );
955     adv_setting_window -> setWindowTitle ( "Advanced Settings" );
956 
957     QVBoxLayout *v_layout = new QVBoxLayout ();
958 
959     // 1
960     QHBoxLayout *layout = new QHBoxLayout ();
961 
962     QLabel *label = new QLabel ( "Default import path:" );
963     label -> setFixedWidth ( 150 );
964     label -> setAlignment ( Qt::AlignRight );
965     layout -> addWidget ( label);
966 
967     import_path_label = new QLabel ( model -> get_user_default_path () . c_str () );
968     import_path_label -> setFrameShape ( QFrame::Panel );
969     import_path_label -> setFrameShadow ( QFrame::Sunken );
970     layout -> addWidget ( import_path_label );
971 
972     QPushButton *edit = new QPushButton ( "Edit" );
973     connect ( edit, SIGNAL ( clicked () ), this, SLOT ( edit_import_path () ) );
974     edit -> setFixedSize ( 30, 20 );
975     layout -> addWidget ( edit );
976 
977     v_layout -> addLayout ( layout );
978     v_layout -> addStretch ( 1 );
979 
980     // last
981     layout = new QHBoxLayout ();
982     layout -> setAlignment ( Qt::AlignBottom | Qt::AlignRight );
983 
984     QPushButton *done = new QPushButton ( "Done" );
985     connect ( done, SIGNAL ( clicked () ), adv_setting_window, SLOT ( close () ) );
986 
987     layout -> addWidget ( done );
988     v_layout -> addLayout ( layout );
989 
990     adv_setting_window -> setLayout ( v_layout );
991 
992     adv_setting_window -> show ();
993 }
994 */
995 
commit_config()996 void SRAConfigView :: commit_config ()
997 {
998     if ( ! model -> commit () )
999         QMessageBox::information ( this, "", "Error saving changes" );
1000 
1001     apply_btn -> setDisabled ( true );
1002     discard_btn -> setDisabled ( true );
1003 }
1004 
reload_config()1005 void SRAConfigView :: reload_config ()
1006 {
1007     model -> reload ();
1008     load_settings ();
1009 
1010    if ( ! model -> config_changed () )
1011    {
1012        apply_btn -> setDisabled ( true );
1013        discard_btn -> setDisabled ( true );
1014    }
1015 }
1016 
modified_config()1017 void SRAConfigView :: modified_config ()
1018 {
1019     if ( model -> config_changed () ) // this wont trigger on workspace addition yet
1020     {
1021         apply_btn -> setDisabled ( false );
1022         discard_btn -> setDisabled ( false );
1023     }
1024 }
1025 
default_config()1026 void SRAConfigView :: default_config ()
1027 {
1028     model -> set_remote_enabled ( true );
1029     model -> set_global_cache_enabled ( true );
1030     model -> set_site_enabled ( true );
1031 
1032     load_settings ();
1033 
1034     emit dirty_config ();
1035 }
1036 
toggle_remote_enabled(int toggled)1037 void SRAConfigView :: toggle_remote_enabled ( int toggled )
1038 {
1039     if ( toggled == 1 )
1040     {
1041         qDebug () << "remote_enabled: yes";
1042         model -> set_remote_enabled ( true );
1043     }
1044     else
1045     {
1046         qDebug () << "remote_enabled: no";
1047         model -> set_remote_enabled ( false );
1048     }
1049 
1050     emit dirty_config ();
1051 }
1052 
toggle_local_caching(int toggled)1053 void SRAConfigView :: toggle_local_caching ( int toggled )
1054 {
1055     if ( toggled == 1 )
1056     {
1057         qDebug () << "local_caching: yes";
1058         model -> set_global_cache_enabled ( true );
1059     }
1060     else
1061     {
1062         qDebug () << "local_caching: no";
1063         model -> set_global_cache_enabled ( false );
1064     }
1065 
1066     emit dirty_config ();
1067 }
1068 
toggle_use_site(int toggled)1069 void SRAConfigView :: toggle_use_site ( int toggled )
1070 {
1071     if ( toggled == 1 )
1072     {
1073         qDebug () << "use_site: yes";
1074         model -> set_site_enabled ( true );
1075 
1076     }
1077     else
1078     {
1079         qDebug () << "use_site: no";
1080         model -> set_site_enabled ( false );
1081     }
1082 
1083     emit dirty_config ();
1084 }
1085 
toggle_use_proxy(int toggled)1086 void SRAConfigView :: toggle_use_proxy ( int toggled )
1087 {
1088     if ( toggled == 1 )
1089     {
1090         qDebug () << "use_proxy: yes";
1091         model -> set_proxy_enabled ( true );
1092         proxyEditor -> setDisabled ( false );
1093     }
1094     else
1095     {
1096         qDebug () << "use_proxy: no";
1097         model -> set_proxy_enabled ( false );
1098         proxyEditor -> setDisabled ( true );
1099     }
1100 
1101     emit dirty_config ();
1102 }
1103 
toggle_allow_all_certs(int toggled)1104 void SRAConfigView :: toggle_allow_all_certs ( int toggled )
1105 {
1106     if ( toggled == 1 )
1107     {
1108         qDebug () << "set_allow_all_certs: yes";
1109         model -> set_allow_all_certs ( true );
1110     }
1111     else
1112     {
1113         qDebug () << "set_allow_all_certs: no";
1114         model -> set_allow_all_certs ( false );
1115     }
1116 
1117     emit dirty_config ();
1118 }
1119 
edit_proxy_path()1120 void SRAConfigView :: edit_proxy_path ()
1121 {
1122     QString text = proxyEditor -> text ();
1123 
1124     if ( text . isEmpty () )
1125         return;
1126 
1127     proxy_string = &text;
1128 
1129     if ( proxyEditor -> hasFocus () )
1130         proxyEditor -> clearFocus ();
1131 
1132     qDebug () << "set new proxy path: " << text;
1133     //model -> set_proxy_path ( proxy_string -> toStdString () );
1134 
1135     //emit dirty_config ();
1136 }
1137 
1138 /*
1139 void SRAConfigView :: edit_import_path ()
1140 {
1141     std :: string path = model -> get_user_default_path () . c_str ();
1142 
1143     if ( ! model -> path_exists ( path ) )
1144         path = model -> get_home_path ();
1145 
1146     if ( ! model -> path_exists ( path ) )
1147         path = model -> get_current_path ();
1148 
1149     QString e_path = QFileDialog :: getOpenFileName ( adv_setting_window
1150                                                     , ""
1151                                                     , path . c_str () );
1152 
1153 
1154     if ( e_path . isEmpty () )
1155         return;
1156 
1157     import_path_label -> setText ( e_path );
1158     model -> set_user_default_path ( e_path . toStdString () . c_str () );
1159 
1160     emit dirty_config ();
1161 }
1162 
1163 
1164 void SRAConfigView :: edit_public_path ()
1165 {
1166     qDebug () << public_workspace -> ngc_id;
1167     if ( select_public_location ( model, this ) )
1168     {
1169         public_workspace -> path_label -> setText ( model -> get_public_path () . c_str () );
1170 
1171         emit dirty_config ();
1172     }
1173 }
1174 
1175 void SRAConfigView :: edit_workspace_path ()
1176 {
1177     foreach ( WorkspaceItem *item,  protected_workspaces )
1178     {
1179         if ( sender () == item -> edit_button )
1180         {
1181             qDebug () << item -> ngc_id;
1182 
1183             if ( select_protected_location ( model, item -> ngc_id, this ) )
1184             {
1185                 QString path =  model -> get_workspace_path ( item -> ngc_id ) . c_str ();
1186                 item -> path_label -> setText ( path );
1187                 import_path_label -> setText ( path );
1188 
1189                 emit dirty_config ();
1190             }
1191 
1192             return;
1193         }
1194     }
1195 }
1196 
1197 */
1198