]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/YQUI_builtins.cc
merge latest qt3 commits
[duncan/yast2-qt4.git] / src / YQUI_builtins.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:         YUIQt_builtins.cc
14
15   Author:       Stefan Hundhammer <sh@suse.de>
16
17   Textdomain    "packages-qt"
18
19 /-*/
20
21 #define USE_QT_CURSORS          1
22 #define FORCE_UNICODE_FONT      0
23
24 #include <sys/stat.h>
25 #include <unistd.h>
26
27 #include <QCursor>
28 #include <QFileDialog>
29 #include <QX11Info>
30 #include <QMessageBox>
31 #include <QPixmap>
32 #include <QInputDialog>
33
34 #define y2log_component "qt-ui"
35 #include <ycp/y2log.h>
36
37 #include "YQUI.h"
38 #include "YEvent.h"
39 #include "YMacroRecorder.h"
40 #include "YUISymbols.h"
41 #include "YQDialog.h"
42 #include "YQSignalBlocker.h"
43
44 #include "utf8.h"
45 #include "YQi18n.h"
46
47 #include <X11/Xlib.h>
48
49
50 #define DEFAULT_MACRO_FILE_NAME         "macro.ycp"
51
52
53
54 YCPString
55 YQUI::glyph( const YCPSymbol & glyphSymbol )
56 {
57     string sym = glyphSymbol->symbol();
58     QChar unicodeChar;
59
60     // Hint: Use 'xfd' to view characters available in the Unicode font.
61
62     if      ( sym == YUIGlyph_ArrowLeft         )       unicodeChar = QChar( 0x2190 );
63     else if ( sym == YUIGlyph_ArrowRight        )       unicodeChar = QChar( 0x2192 );
64     else if ( sym == YUIGlyph_ArrowUp           )       unicodeChar = QChar( 0x2191 );
65     else if ( sym == YUIGlyph_ArrowDown         )       unicodeChar = QChar( 0x2193 );
66     else if ( sym == YUIGlyph_CheckMark         )       unicodeChar = QChar( 0x2714 );
67     else if ( sym == YUIGlyph_BulletArrowRight  )       unicodeChar = QChar( 0x279c );
68     else if ( sym == YUIGlyph_BulletCircle      )       unicodeChar = QChar( 0x274d );
69     else if ( sym == YUIGlyph_BulletSquare      )       unicodeChar = QChar( 0x274f );
70     else return YCPString( "" );
71
72     QString qstr( unicodeChar );
73
74     return YCPString( toUTF8( qstr ) );
75 }
76
77
78 YCPValue YQUI::runPkgSelection( YWidget * packageSelector )
79 {
80     y2milestone( "Running package selection..." );
81     YCPValue input = YCPVoid();
82
83     try
84     {
85         input = evaluateUserInput();
86     }
87     catch (const std::exception & e)
88     {
89         y2error( "Caught std::exception: %s", e.what() );
90         y2error( "This is a libzypp problem. Do not file a bug against the UI!" );
91     }
92     catch (...)
93     {
94         y2error( "Caught unspecified exception." );
95         y2error( "This is a libzypp problem. Do not file a bug against the UI!" );
96     }
97
98     y2milestone( "Package selection done - returning %s", input->toString().c_str() );
99
100     return input;
101 }
102
103
104 void YQUI::makeScreenShot( std::string stl_filename )
105 {
106
107     //
108     // Grab the pixels off the screen
109     //
110
111     QWidget * dialog = (QWidget *) YDialog::currentDialog()->widgetRep();
112     QPixmap screenShot = QPixmap::grabWindow( dialog->winId() );
113     XSync( QX11Info::display(), false );
114     QString fileName ( stl_filename.c_str() );
115     bool interactive = false;
116
117     if ( fileName.isEmpty() )
118     {
119         interactive = true;
120
121         // Open a file selection box. Figure out a reasonable default
122         // directory / file name.
123
124         if ( screenShotNameTemplate.isEmpty() )
125         {
126             //
127             // Initialize screen shot directory
128             //
129
130             QString home = QDir::homePath();
131             char * ssdir = getenv("Y2SCREENSHOTS");
132             QString dir  = ssdir ? ssdir : "yast2-screen-shots";
133
134             if ( home == "/" )
135             {
136                 // Special case: $HOME is not set. This is normal in the inst-sys.
137                 // In this case, rather than simply dumping all screen shots into
138                 // /tmp which is world-writable, let's try to create a subdirectory
139                 // below /tmp with restrictive permissions.
140                 // If that fails, trust nobody - in particular, do not suggest /tmp
141                 // as the default in the file selection box.
142
143                 dir = "/tmp/" + dir;
144
145                 if ( mkdir( qPrintable(dir), 0700 ) == -1 )
146                     dir = "";
147             }
148             else
149             {
150                 // For all others let's create a directory ~/yast2-screen-shots and
151                 // simply ignore if this is already present. This gives the user a
152                 // chance to create symlinks to a better location if he wishes so.
153
154                 dir = home + "/" + dir;
155                 (void) mkdir( qPrintable(dir), 0750 );
156             }
157
158             screenShotNameTemplate = dir + "/%s-%03d.png";
159         }
160
161
162         //
163         // Figure out a file name
164         //
165
166         const char * baseName = moduleName();
167         if ( ! baseName ) baseName = "scr";
168         int no = screenShotNo[ baseName ];
169         fileName.sprintf( qPrintable(screenShotNameTemplate), baseName, no );
170         y2debug( "screenshot: %s", qPrintable(fileName) );
171
172         {
173             YQSignalBlocker sigBlocker( _user_input_timer );
174
175             fileName = askForSaveFileName( fileName, QString( "*.png" ) , _( "Save screen shot to..." ) );
176         }
177
178         if ( fileName.isEmpty() )
179         {
180             y2debug( "Save screen shot canceled by user" );
181             return;
182         }
183
184         screenShotNo.insert( baseName, ++no );
185     } // if fileName.isEmpty()
186
187
188     //
189     // Actually save the screen shot
190     //
191
192     y2debug( "Saving screen shot to %s", qPrintable(fileName) );
193     bool success = screenShot.save( fileName, "PNG" );
194
195     if ( ! success )
196     {
197         y2error( "Couldn't save screen shot %s", qPrintable(fileName) );
198
199         if ( interactive )
200         {
201             QMessageBox::warning( 0,                                    // parent
202                                   "Error",                              // caption
203                                   QString( "Couldn't save screen shot\nto %1" ).arg( fileName ),
204                                   QMessageBox::Ok | QMessageBox::Default,       // button0
205                                   Qt::NoButton,                         // button1
206                                   Qt::NoButton );                       // button2
207         }
208     }
209
210     if ( recordingMacro() )
211     {
212         macroRecorder->beginBlock();
213         YDialog::currentDialog()->saveUserInput( macroRecorder );
214         macroRecorder->recordMakeScreenShot( true, qPrintable(fileName) );
215         macroRecorder->recordUserInput( YCPVoid() );
216         macroRecorder->endBlock();
217     }
218 }
219
220
221 void YQUI::askSaveLogs()
222 {
223     QString fileName = askForSaveFileName( "/tmp/y2logs.tgz",                   // startWith
224                                            "*.tgz *.tar.gz",                    // filter
225                                            "Save y2logs to..." );               // headline
226
227     if ( ! fileName.isEmpty() )
228     {
229         QString saveLogsCommand = "/sbin/save_y2logs";
230
231         if ( access( saveLogsCommand.toAscii(), X_OK ) == 0 )
232         {
233             saveLogsCommand += " '" + fileName + "'";
234             y2milestone( "Saving y2logs: %s", qPrintable(saveLogsCommand) );
235             int result = system( qPrintable(saveLogsCommand) );
236
237             if ( result != 0 )
238             {
239                 y2error( "Error saving y2logs: \"%s\" exited with %d",
240                          qPrintable(saveLogsCommand), result );
241                 QMessageBox::warning( 0,                                        // parent
242                                       "Error",                                  // caption
243                                       QString( "Couldn't save y2logs to %1 - "
244                                                "exit code %2" ).arg( fileName ).arg( result ),
245                                       QMessageBox::Ok | QMessageBox::Default,   // button0
246                                       QMessageBox::NoButton,                    // button1
247                                       QMessageBox::NoButton );                  // button2
248             }
249             else
250             {
251                 y2milestone( "y2logs saved to %s", qPrintable(fileName) );
252             }
253         }
254         else
255         {
256             y2error( "Error saving y2logs: Command %s not found",
257                      qPrintable(saveLogsCommand) );
258
259             QMessageBox::warning( 0,                                            // parent
260                                   "Error",                                      // caption
261                                   QString( "Couldn't save y2logs to %1:\n"
262                                            "Command %2 not found" ).arg( fileName ).arg( saveLogsCommand ),
263                                   QMessageBox::Ok | QMessageBox::Default,       // button0
264                                   QMessageBox::NoButton,                        // button1
265                                   QMessageBox::NoButton );                      // button2
266         }
267     }
268 }
269
270
271 void YQUI::askConfigureLogging()
272 {
273     bool okButtonPressed = false;
274     QStringList items;
275     items << "Debug logging off"
276           << "Debug logging on";
277
278     QString result = QInputDialog::getItem( _main_win,
279                                           tr("YaST2 Logging"),
280                                           tr("Configure YaST2 Logging:"),
281                                           items, 0, get_log_debug() ? 1 : 0, &okButtonPressed);
282     if ( okButtonPressed )
283     {
284         set_log_debug( result.endsWith( "on" ) );
285         y2milestone( "Changing logging: %s - %s", qPrintable(result),
286                      get_log_debug() ? "y2debug on" : "y2debug off" );
287     }
288 }
289
290
291 void YQUI::toggleRecordMacro()
292 {
293     if ( recordingMacro() )
294     {
295         stopRecordMacro();
296         normalCursor();
297
298         QMessageBox::information( 0,                                            // parent
299                                   "YaST2 Macro Recorder",                       // caption
300                                   "Macro recording done.",                      // text
301                                   QMessageBox::Ok | QMessageBox::Default,       // button0
302                                   QMessageBox::NoButton,                        // button1
303                                   QMessageBox::NoButton );                      // button2
304     }
305     else
306     {
307         normalCursor();
308
309         QString filename =
310             QFileDialog::getSaveFileName( 0,
311                                           "Select Macro File to Record to",
312                                           DEFAULT_MACRO_FILE_NAME,              // startWith
313                                           "*.ycp"                             // filter
314                                           );
315
316         if ( ! filename.isEmpty() )     // file selection dialog has been cancelled
317         {
318             recordMacro( qPrintable(filename) );
319         }
320     }
321 }
322
323
324 void YQUI::askPlayMacro()
325 {
326     normalCursor();
327
328     QString filename =
329         QFileDialog::getOpenFileName( 0,
330                                       "Select Macro File to Play",
331                                       DEFAULT_MACRO_FILE_NAME,          // startWith
332                                       "*.ycp" );
333     busyCursor();
334
335     if ( ! filename.isEmpty() ) // file selection dialog has been cancelled
336     {
337         playMacro( qPrintable(filename) );
338
339         // Do special magic to get out of any UserInput() loop right now
340         // without doing any harm - otherwise this would hang until the next
341         // mouse click on a PushButton etc.
342
343         sendEvent( new YEvent() );
344
345         if ( _do_exit_loop )
346         {
347             _eventLoop->exit();
348         }
349     }
350 }
351
352
353
354 YCPValue YQUI::askForExistingDirectory( const YCPString & startDir,
355                                          const YCPString & headline )
356 {
357     normalCursor();
358
359     QString dir_name =
360         QFileDialog::getExistingDirectory( _main_win,
361                                            fromUTF8( headline->value() ),
362                                            fromUTF8( startDir->value() ) );
363     busyCursor();
364
365     if ( dir_name.isEmpty() )   // this includes dir_name.isNull()
366         return YCPVoid();       // nothing selected -> return 'nil'
367
368     return YCPString( toUTF8( dir_name ) );
369 }
370
371
372 YCPValue YQUI::askForExistingFile( const YCPString & startWith,
373                                    const YCPString & filter,
374                                    const YCPString & headline )
375 {
376     normalCursor();
377
378     QString file_name =
379         QFileDialog::getOpenFileName( _main_win,                        // parent
380                                       fromUTF8( headline->value() ),
381                                       fromUTF8( startWith->value() ),
382                                       fromUTF8( filter->value() ) );
383     busyCursor();
384
385     if ( file_name.isEmpty() )  // this includes file_name.isNull()
386         return YCPVoid();       // nothing selected -> return 'nil'
387
388     return YCPString( toUTF8( file_name ) );
389 }
390
391
392 YCPValue YQUI::askForSaveFileName( const YCPString & startWith,
393                                    const YCPString & filter,
394                                    const YCPString & headline )
395 {
396     normalCursor();
397
398     QString file_name = askForSaveFileName( fromUTF8( startWith->value() ),
399                                             fromUTF8( filter->value() ),
400                                             fromUTF8( headline->value() ) );
401     busyCursor();
402
403     if ( file_name.isEmpty() )          // this includes file_name.isNull()
404         return YCPVoid();               // nothing selected -> return 'nil'
405
406     return YCPString( toUTF8( file_name ) );
407 }
408
409
410
411 QString YQUI::askForSaveFileName( const QString & startWith,
412                                   const QString & filter,
413                                   const QString & headline )
414 {
415     QString file_name;
416     bool try_again = false;
417
418     do
419     {
420         // Leave the mouse cursor alone - this function might be called from
421         // some other widget, not only from UI::AskForSaveFileName().
422
423         file_name = QFileDialog::getSaveFileName( _main_win,
424                                                   headline,
425                                                   startWith,
426                                                   filter );
427
428         if ( file_name.isEmpty() )      // this includes file_name.isNull()
429             return QString::null;
430
431
432         if ( access( qPrintable(file_name), F_OK ) == 0 )    // file exists?
433         {
434             QString msg;
435
436             if ( access( qPrintable(file_name), W_OK ) == 0 )
437             {
438                 // Confirm if the user wishes to overwrite an existing file
439                 msg = ( _( "%1 exists! Really overwrite?" ) ).arg( file_name );
440             }
441             else
442             {
443                 // Confirm if the user wishes to overwrite a write-protected file %1
444                 msg = ( _( "%1 exists and is write-protected!\nReally overwrite?" ) ).arg( file_name );
445             }
446
447             int button_no = QMessageBox::information( _main_win,
448                                                       // Window title for confirmation dialog
449                                                       _( "Confirm"   ),
450                                                       msg,
451                                                       _( "C&ontinue" ),
452                                                       _( "&Cancel"   ) );
453             try_again = ( button_no != 0 );
454         }
455
456     } while ( try_again );
457
458     return file_name;
459 }
460
461
462 // EOF