summaryrefslogtreecommitdiffstats
path: root/src/modules/dialog/libkvidialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules/dialog/libkvidialog.cpp')
-rw-r--r--src/modules/dialog/libkvidialog.cpp920
1 files changed, 920 insertions, 0 deletions
diff --git a/src/modules/dialog/libkvidialog.cpp b/src/modules/dialog/libkvidialog.cpp
new file mode 100644
index 00000000..dd7cf391
--- /dev/null
+++ b/src/modules/dialog/libkvidialog.cpp
@@ -0,0 +1,920 @@
+//=============================================================================
+//
+// File : libkvidialog.cpp
+// Creation date : Sat Sep 15 2001 01:13:25 by Szymon Stefanek
+//
+// This file is part of the KVirc irc client distribution
+// Copyright (C) 2001-2005 Szymon Stefanek (pragma at kvirc dot net)
+//
+// This program 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 opinion) any later version.
+//
+// This program 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, write to the Free Software Foundation,
+// Inc. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+//
+//=============================================================================
+
+
+#include "libkvidialog.h"
+
+#include <qmessagebox.h>
+#include <qlayout.h>
+#include "kvi_tal_hbox.h"
+#include <qlineedit.h>
+#ifdef COMPILE_USE_QT4
+ #include <q3multilineedit.h>
+ #define QMultiLineEdit Q3MultiLineEdit
+ #include <qdesktopwidget.h>
+#else
+ #include <qmultilineedit.h>
+#endif
+#include <qevent.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+
+#include "kvi_locale.h"
+#include "kvi_module.h"
+#include "kvi_modulemanager.h"
+#include "kvi_error.h"
+#include "kvi_app.h"
+#include "kvi_iconmanager.h"
+#include "kvi_console.h"
+#include "kvi_iconmanager.h"
+#include "kvi_kvs_script.h"
+#include "kvi_msgbox.h"
+
+static KviPointerList<QWidget> * g_pDialogModuleDialogList;
+
+KviKvsCallbackMessageBox::KviKvsCallbackMessageBox(
+ const QString &szCaption,
+ const QString &szText,
+ const QString &szIcon,
+ const QString &szButton0,
+ const QString &szButton1,
+ const QString &szButton2,
+ const QString &szCode,
+ KviKvsVariantList * pMagicParams,
+ KviWindow * pWindow,bool modal)
+: QMessageBox(
+ szCaption,
+ szText,
+ QMessageBox::NoIcon,
+ szButton0.isEmpty() ? QMessageBox::NoButton : QMessageBox::Ok | QMessageBox::Default,
+ szButton1.isEmpty() ? QMessageBox::NoButton : (szButton2.isEmpty() ? QMessageBox::No | QMessageBox::Escape : QMessageBox::No),
+ szButton2.isEmpty() ? QMessageBox::NoButton : QMessageBox::Cancel | QMessageBox::Escape,
+ 0,0,modal) ,
+ KviKvsCallbackObject("dialog.message",pWindow,szCode,pMagicParams,0)
+{
+ g_pDialogModuleDialogList->append(this);
+#ifndef COMPILE_USE_QT4
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC)));
+#endif
+
+ QPixmap * pix = g_pIconManager->getImage(szIcon);
+
+ if(pix)setIconPixmap(*pix);
+ else {
+ if(KviQString::equalCI(szIcon,"information"))setIcon(QMessageBox::Information);
+ else if(KviQString::equalCI(szIcon,"warning"))setIcon(QMessageBox::Warning);
+ else if(KviQString::equalCI(szIcon,"critical"))setIcon(QMessageBox::Critical);
+ }
+ if(!szButton0.isEmpty())setButtonText(QMessageBox::Ok,szButton0);
+ if(!szButton1.isEmpty())setButtonText(QMessageBox::No,szButton1);
+ if(!szButton2.isEmpty())setButtonText(QMessageBox::Cancel,szButton2);
+}
+
+KviKvsCallbackMessageBox::~KviKvsCallbackMessageBox()
+{
+ g_pDialogModuleDialogList->removeRef(this);
+}
+
+void KviKvsCallbackMessageBox::done(int code)
+{
+ QMessageBox::done(code);
+
+ kvs_int_t iVal = 0;
+
+ switch(code)
+ {
+ case QMessageBox::No: iVal = 1; break;
+ case QMessageBox::Cancel: iVal = 2; break;
+ }
+
+ KviKvsVariantList params;
+ params.append(new KviKvsVariant(iVal));
+
+ execute(&params);
+
+ delete this;
+}
+
+
+/*
+ @doc: dialog.message
+ @type:
+ command
+ @title:
+ dialog.message
+ @short:
+ Shows a message box
+ @syntax:
+ dialog.message [-b] (<caption>,<message_text>,<icon>,<button0>[,<button1>[,<button2>[,<magic1>[,<magic2>[...]]]]])
+ {
+ <callback_command>
+ }
+ @description:
+ Shows a message dialog box with the specified <caption> , <message_text> , <icon> and
+ buttons.[br]
+ <caption> is a text string that will appear in the caption of the dialog box.[br]
+ <message_text> is a text string that will appear in the dialog box and can contain HTML formatting.[br]
+ <icon> is an [doc:image_id]image identifier[/doc] that defines an icon to be placed in the dialog box.
+ <icon> can be a relative or absolute path to an image file , a signed number (in that case it defines
+ an internal KVIrc image) or one of the special strings "critical", "information" and "warning".[br]
+ <button0> is the text of the first button (on the left).[br]
+ <button1> is the text of the second button (if empty or not given at all, only one button will appear in the dialog).[br]
+ <button2> is the text of the third button (if empty or not given, only two buttons will appear in the dialog).[br]
+ The first button is always the default button: it is activated when the user presses the
+ enter key. The thirs, or the second if the third is not present, is the escape button
+ and is activated when the user presses the Esc key.[br]
+ <magic1>,<magic2>... are the magic parameters: evaluated at dialog.message call time and passed
+ to the <callback_command> as positional parameters.[br]
+ If the -b or -modal switch is specified the dialog will have non-blocking modal behaviour:
+ it will appear above its parent widget and block its input until it's closed.[br]
+ Once the dialog has been shown , the user will click one of the buttons. At this point the dialog
+ is hidden and the <callback_command> is executed passing the number of the button clicked
+ as $0 and the magic parameters as positional parameters $1 , $2 , $3....[br]
+ Please note that if the user closes the window with the window manager close button ,
+ the action is interpreted as a button2 click (that is usually sth as "Cancel").[br]
+ @examples:
+ [example]
+ [comment]# Just a warning dialog[/comment]
+ dialog.message("Warning","You're being <b>warned</b>",warning,"Ok"){ echo The user clicked OK; }
+ [comment]# A question[/comment]
+ dialog.message("And now ?","What do you want to do ?",information,"Go home","Watch TV","Scream")
+ {
+ if($0 == 0)echo "The user want's to go home"
+ else if($0 == 1)echo "The user want's to watch TV"
+ else echo "The user wants to scream!"
+ }
+ [/example]
+*/
+
+static bool dialog_kvs_cmd_message(KviKvsModuleCallbackCommandCall * c)
+{
+ QString szCaption,szMessage,szIcon,szButton0,szButton1,szButton2;
+ KviKvsVariantList params;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption)
+ KVSM_PARAMETER("message",KVS_PT_STRING,0,szMessage)
+ KVSM_PARAMETER("icon",KVS_PT_STRING,0,szIcon)
+ KVSM_PARAMETER("button0",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton0)
+ KVSM_PARAMETER("button1",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton1)
+ KVSM_PARAMETER("button2",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton2)
+ KVSM_PARAMETER("magic",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,params)
+ KVSM_PARAMETERS_END(c)
+ bool modal;
+ if(c->hasSwitch('b',"modal")) modal=true;
+ else modal=false;
+ QString szCmd = c->callback()->code();
+
+ KviKvsCallbackMessageBox * box = new KviKvsCallbackMessageBox(
+ szCaption,szMessage,szIcon,szButton0,szButton1,szButton2,szCmd,&params,c->window(),modal);
+ box->show();
+
+ return true;
+}
+
+
+
+KviKvsCallbackTextInput::KviKvsCallbackTextInput(
+ const QString &szCaption,
+ const QString &szLabel,
+ const QString &szDefaultText,
+ const QString &szIcon,
+ bool bMultiLine,
+ const QString &szButton0,
+ const QString &szButton1,
+ const QString &szButton2,
+ const QString &szCode,
+ KviKvsVariantList * pMagicParams,
+ KviWindow * pWindow,bool modal)
+ : QDialog(), KviKvsCallbackObject("dialog.textinput",pWindow,szCode,pMagicParams,0)
+{
+ g_pDialogModuleDialogList->append(this);
+ setIcon(*(g_pIconManager->getSmallIcon(KVI_SMALLICON_KVIRC)));
+ setModal(modal);
+ setCaption(szCaption);
+
+ QGridLayout * g = new QGridLayout(this,2,3,5,5);
+
+ QPixmap * pix = g_pIconManager->getImage(szIcon);
+
+ if(pix)
+ {
+ QLabel * il = new QLabel(this);
+ il->setPixmap(*pix);
+ il->setAlignment(Qt::AlignCenter);
+ g->addWidget(il,0,0);
+ QLabel * tl = new QLabel(szLabel,this);
+ g->addWidget(tl,0,1);
+ } else {
+ QLabel * tl = new QLabel(szLabel,this);
+ g->addMultiCellWidget(tl,0,0,0,1);
+ }
+
+ g->setColStretch(1,1);
+
+ m_bMultiLine = bMultiLine;
+
+ if(m_bMultiLine)
+ {
+ m_pEdit = new QMultiLineEdit(this);
+ ((QMultiLineEdit *)m_pEdit)->setText(szDefaultText);
+ } else {
+ m_pEdit = new QLineEdit(this);
+ ((QLineEdit *)m_pEdit)->setText(szDefaultText);
+ }
+
+ g->addMultiCellWidget(m_pEdit,1,1,0,1);
+
+ KviTalHBox * box = new KviTalHBox(this);
+ g->addMultiCellWidget(box,2,2,0,1);
+
+ m_iEscapeButton = 0;
+ m_iDefaultButton = 0;
+
+ if(!szButton0.isEmpty())
+ {
+ QString szB = szButton0;
+ bool bDef = false;
+ if(KviQString::equalCIN(szB,"default=",8))
+ {
+ bDef = true;
+ szB.remove(0,8);
+ m_iDefaultButton = 0;
+ } else if(KviQString::equalCIN(szB,"escape=",7))
+ {
+ szB.remove(0,7);
+ m_iEscapeButton = 0;
+ }
+ QPushButton * pb1 = new QPushButton(szB,box);
+ if(bDef)pb1->setDefault(true);
+ connect(pb1,SIGNAL(clicked()),this,SLOT(b0Clicked()));
+ }
+
+ if(!szButton1.isEmpty())
+ {
+ QString szB = szButton1;
+ bool bDef = false;
+ if(KviQString::equalCIN(szB,"default=",8))
+ {
+ bDef = true;
+ szB.remove(0,8);
+ m_iDefaultButton = 1;
+ } else if(KviQString::equalCIN(szB,"escape=",7))
+ {
+ szB.remove(0,7);
+ m_iEscapeButton = 1;
+ }
+ QPushButton * pb2 = new QPushButton(szB,box);
+ if(bDef)pb2->setDefault(true);
+ connect(pb2,SIGNAL(clicked()),this,SLOT(b1Clicked()));
+ }
+
+ if(!szButton2.isEmpty())
+ {
+ QString szB = szButton2;
+ bool bDef = false;
+ if(KviQString::equalCIN(szB,"default=",8))
+ {
+ bDef = true;
+ szB.remove(0,8);
+ m_iDefaultButton = 2;
+ } else if(KviQString::equalCIN(szB,"escape=",7))
+ {
+ szB.remove(0,7);
+ m_iEscapeButton = 2;
+ }
+ QPushButton * pb3 = new QPushButton(szB,box);
+ if(bDef)pb3->setDefault(true);
+ connect(pb3,SIGNAL(clicked()),this,SLOT(b2Clicked()));
+ }
+
+}
+
+KviKvsCallbackTextInput::~KviKvsCallbackTextInput()
+{
+ g_pDialogModuleDialogList->removeRef(this);
+}
+
+void KviKvsCallbackTextInput::b0Clicked()
+{
+ done(0+10);
+}
+
+void KviKvsCallbackTextInput::b1Clicked()
+{
+ done(1+10);
+}
+
+void KviKvsCallbackTextInput::b2Clicked()
+{
+ done(2+10);
+}
+
+void KviKvsCallbackTextInput::closeEvent(QCloseEvent *e)
+{
+ e->ignore();
+ done(m_iEscapeButton+10);
+}
+
+void KviKvsCallbackTextInput::done(int code)
+{
+ if(code >= 10)
+ {
+ code -= 10;
+ } else {
+ switch(code)
+ {
+ case QDialog::Accepted:
+ code = m_iDefaultButton;
+ break;
+ default:
+ code = m_iEscapeButton;
+ break;
+ }
+ }
+
+ QString txt;
+
+ if(m_bMultiLine)
+ {
+ txt = ((QMultiLineEdit *)m_pEdit)->text();
+ } else {
+ txt = ((QLineEdit *)m_pEdit)->text();
+ }
+
+ KviKvsVariantList params;
+ params.append(new KviKvsVariant((kvs_int_t)code));
+ params.append(new KviKvsVariant(txt));
+
+ execute(&params);
+
+ //QDialog::done(code);
+
+ delete this;
+}
+
+void KviKvsCallbackTextInput::showEvent(QShowEvent *e)
+{
+ move((g_pApp->desktop()->width() - width())/2,(g_pApp->desktop()->height() - height()) / 2);
+ QDialog::showEvent(e);
+}
+
+
+
+/*
+ @doc: dialog.textinput
+ @type:
+ command
+ @title:
+ dialog.textinput
+ @short:
+ Shows a dialog that accepts user input as text
+ @syntax:
+ dialog.textinput [-d=<default text>] [-i=<icon>] [-m] [-b] (<caption>,<info_text>,<button0>[,<button1>[,<button2>[,<magic1>[,<magic2>[...]]]]])
+ {
+ <callback_command>
+ }
+ @switches:
+ !sw: -d=<default_text> | --default=<default_text>
+ Set the initial text input value to <default_text>
+ !sw: -i=<icon> | --icon=<icon>
+ Display the specified icon, just of the left of the informational text
+ !sw: -m | --multiline
+ Input multiline text instead of single line
+ @description:
+ Shows a text input dialog box with the specified <caption> , <info_text> , <icon> and
+ buttons.[br]
+ <caption> is a text string that will appear in the caption of the dialog box.[br]
+ <info_text> is a fixed text string that will appear in the dialog box and can contain HTML formatting.[br]
+ <button0> is the text of the first button (on the left).[br]
+ <button1> is the text of the second button (if empty or not given at all, only one button will appear in the dialog).[br]
+ <button2> is the text of the third button (if empty or not given, only two buttons will appear in the dialog).[br]
+ If one of the text strings starts with a "default=" prefix then the button is assumed
+ to be the default button of the dialog and will be also activated when the user presses enter.
+ If the -m switch is used , the dialog will be a multi-line text input, otherwise the user will be able to
+ input only a single line of text.[br]
+ If the -d switch is used , the initial text input value is set to <default text>.[br]
+ If the -i switch is used , the dialog displays also the icon <icon> , just on the left ot the <info_text>[br]
+ If the -b or -modal switch is specified the dialog will have non-blocking modal behaviour:
+ it will appear above its parent widget and block its input until it's closed.[br]
+ In that case <icon> is an [doc:image_id]image identifier[/doc] (can be a relative or absolute
+ path to an image file or a signed number (in that case it defines an internal KVIrc image).[br]
+ <magic1>,<magic2>... are the magic parameters: evaluated at dialog.textinput call time and passed
+ to the <callback_command> as positional parameters.[br]
+ Once the dialog has been shown , the user will click one of the buttons. At this point the dialog
+ is hidden and the <callback_command> is executed passing the text input value in $1, the number of the button clicked
+ as $0, and the magic parameters as positional parameters $2 , $3 , $4....[br]
+ Please note that if the user closes the window with the window manager close button ,
+ the action is interpreted as a button2 click (that is usually sth as "Cancel").[br]
+ @examples:
+ [example]
+ [comment]# We need a single line "reason"[/comment]
+ dialog.textinput -d="Working !" (Away,<center>Please enter the <h1>away message</h1></center>,"Ok","Cancel")
+ {
+ switch($0)
+ {
+ case(0):
+ away $1-
+ break;
+ default:
+ # Cancelled
+ break;
+ }
+ }
+ [/example]
+*/
+
+static bool dialog_kvs_cmd_textinput(KviKvsModuleCallbackCommandCall * c)
+{
+ QString szCaption,szInfoText,szIcon,szDefaultText,szButton0,szButton1,szButton2;
+ KviKvsVariantList params;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption)
+ KVSM_PARAMETER("info_text",KVS_PT_STRING,0,szInfoText)
+ KVSM_PARAMETER("button0",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton0)
+ KVSM_PARAMETER("button1",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton1)
+ KVSM_PARAMETER("button2",KVS_PT_STRING,KVS_PF_OPTIONAL,szButton2)
+ KVSM_PARAMETER("magic",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,params)
+ KVSM_PARAMETERS_END(c)
+
+ QString szCmd = c->callback()->code();
+
+ c->switches()->getAsStringIfExisting('i',"icon",szIcon);
+ c->switches()->getAsStringIfExisting('d',"default",szDefaultText);
+ bool modal;
+ if(c->hasSwitch('b',"modal")) modal=true;
+ else modal=false;
+ KviKvsCallbackTextInput * box = new KviKvsCallbackTextInput(
+ szCaption,szInfoText,szDefaultText,szIcon,c->switches()->find('m',"multiline"),
+ szButton0,szButton1,szButton2,szCmd,&params,c->window(),modal);
+ box->show();
+
+ return true;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+// New KVS
+KviKvsCallbackFileDialog::KviKvsCallbackFileDialog(
+ const QString &szCaption,
+ const QString &szInitialSelection,
+ const QString &szFilter,
+ const QString &szCode,
+ KviKvsVariantList * pMagicParams,
+ KviWindow * pWindow,bool modal)
+ : KviFileDialog(szInitialSelection,szFilter,0,0,modal), KviKvsCallbackObject("dialog.file",pWindow,szCode,pMagicParams,0)
+{
+ g_pDialogModuleDialogList->append(this);
+ setCaption(szCaption);
+}
+
+KviKvsCallbackFileDialog::~KviKvsCallbackFileDialog()
+{
+ g_pDialogModuleDialogList->removeRef(this);
+}
+
+void KviKvsCallbackFileDialog::done(int code)
+{
+ KviFileDialog::done(code);
+ KviKvsVariantList params;
+
+ if(code == QDialog::Accepted)
+ {
+#ifdef COMPILE_KDE_SUPPORT
+ if(mode() == KFile::ExistingOnly)
+#else
+ if(mode() == QFileDialog::ExistingFiles)
+#endif
+ {
+ KviKvsArray * a = new KviKvsArray();
+ QStringList sl = selectedFiles();
+ int idx = 0;
+ for(QStringList::Iterator it = sl.begin();it != sl.end();++it)
+ {
+ a->set(idx,new KviKvsVariant(*it));
+ idx++;
+ }
+ params.append(new KviKvsVariant(a));
+ } else {
+ params.append(new KviKvsVariant(selectedFile()));
+ }
+ } else {
+ params.append(new KviKvsVariant(QString("")));
+ }
+
+ hide(); // ensure we're hidden
+
+ // ugly workaround for the Qt filedialog "destructive accept() before this reference" bug
+ // we can't delete ourselves in this moment.... :(((
+ // ...so skip out of this call stack and ask KviApp to destroy us just
+ // when the control returns to the main loop.
+ // If the module is unloaded then , KviApp will notice it and will NOT delete the dialog
+ g_pApp->collectGarbage(this);
+
+ // calling dialog.unload here WILL lead to a sigsegv (this is SURE
+ // with a lot of qt versions that have the ugly file dialog "accept before this reference" bug)
+ // to avoid it, we can execute the callback triggered by a timer...
+ // ... umpf ...
+ execute(&params);
+}
+
+/*
+ @doc: dialog.file
+ @type:
+ command
+ @title:
+ dialog.file
+ @short:
+ Shows a file dialog
+ @syntax:
+ dialog.file [-b] (<mode>,<caption>[,<initial_selection[,<file_filter>[,<magic1>[,<magic2>[...]]]]]])
+ {
+ <callback_command>
+ }
+ @description:
+ Shows an openfile dialog box with the specified <caption> , <initial_selection> , and <file_filter>.[br]
+ <mode> can be "open" , "openm" , "save" or "dir":[br]
+ "open" causes the dialog to return an existing file[br]
+ "openm" is similar to open but allows returning multiple files as a comma separated list[br]
+ "save" causes the dialog to return any file name (no overwrite confirmation is built in the dialog!)[br]
+ "dir" causes the dialog to return an existing directory name[br]
+ <mode> defaults to "open".[br]
+ <caption> is a text string that will appear in the caption of the dialog box.[br]
+ <initial_selection> can be a directory or filename that will be initially selected in the dialog.[br]
+ Only files matching <file_filter> are selectable. If filter is an empty string, all files are selectable.[br]
+ In the filter string multiple filters can be specified separated by either two semicolons next to each
+ other or separated by newlines. To add two filters, one to show all C++ files and one to show all
+ header files, the filter string could look like "C++ Files (*.cpp *.cc *.C *.cxx *.c++);;Header Files (*.h *.hxx *.h++)"
+ <magic1>,<magic2>... are the magic parameters: evaluated at dialog.message call time and passed
+ to the <callback_command> as positional parameters.[br]
+ If the -b or -modal switch is specified the dialog will have non-blocking modal behaviour:
+ it will appear above its parent widget and block its input until it's closed.[br]
+ Once the dialog has been shown , the user will select an EXISTING file and click either
+ Ok or Cancel. At this point the dialog is hidden and the <callback_command> is executed passing the selected file(s) as $0
+ and the magic parameters as positional parameters $1 , $2 , $3....[br]
+ If the user clicks "Cancel" or does not select any file the positional parameter $0 will be empty.[br]
+ @examples:
+ [example]
+ dialog.file(open,Choose an audio file,/home/pragma/TheAudio.au,"Audio files (*.au *.wav *.snd)")
+ {
+ if("$0" != "")run play $0
+ }
+ [/example]
+*/
+
+//#warning "Examples for these dialogs!"
+
+
+static bool dialog_kvs_cmd_file(KviKvsModuleCallbackCommandCall * c)
+{
+ QString szMode,szCaption,szInitialSelection,szFilter;
+ KviKvsVariantList params;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("mode",KVS_PT_STRING,0,szMode)
+ KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption)
+ KVSM_PARAMETER("initial_selection",KVS_PT_STRING,KVS_PF_OPTIONAL,szInitialSelection)
+ KVSM_PARAMETER("filter",KVS_PT_STRING,KVS_PF_OPTIONAL,szFilter)
+ KVSM_PARAMETER("magic",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,params)
+ KVSM_PARAMETERS_END(c)
+ bool modal;
+ if(c->hasSwitch('b',"modal")) modal=true;
+ else modal=false;
+ QString szCmd = c->callback()->code();
+
+ KviKvsCallbackFileDialog * box = new KviKvsCallbackFileDialog(szCaption,szInitialSelection,szFilter,szCmd,&params,c->window(),modal);
+
+ KviFileDialog::FileMode md = KviFileDialog::ExistingFile;
+
+ if(KviQString::equalCI(szMode,"openm"))md = KviFileDialog::ExistingFiles;
+ else if(KviQString::equalCI(szMode,"save"))md = KviFileDialog::AnyFile;
+ else if(KviQString::equalCI(szMode,"dir"))md = KviFileDialog::DirectoryOnly;
+
+ box->setFileMode(md);
+
+ box->show();
+
+ return true;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+// New KVS
+KviKvsCallbackImageDialog::KviKvsCallbackImageDialog(
+ const QString &szCaption,
+ const QString &szInitialSelection,
+ int iType,
+ int iMaxSize,
+ const QString &szCode,
+ KviKvsVariantList * pMagicParams,
+ KviWindow * pWindow,bool modal)
+ : KviImageDialog(0,szCaption,iType,0,szInitialSelection,iMaxSize,modal), KviKvsCallbackObject("dialog.image",pWindow,szCode,pMagicParams,0)
+{
+ g_pDialogModuleDialogList->append(this);
+}
+
+KviKvsCallbackImageDialog::~KviKvsCallbackImageDialog()
+{
+ g_pDialogModuleDialogList->removeRef(this);
+}
+
+void KviKvsCallbackImageDialog::done(int code)
+{
+ KviImageDialog::done(code);
+ KviKvsVariantList params;
+
+ if(code == QDialog::Accepted)
+ {
+ params.append(new KviKvsVariant(selectedImage()));
+ } else {
+ params.append(new KviKvsVariant(QString("")));
+ }
+
+ hide(); // ensure we're hidden
+
+ // ugly workaround for the Qt filedialog "destructive accept() before this reference" bug
+ // we can't delete ourselves in this moment.... :(((
+ // ...so skip out of this call stack and ask KviApp to destroy us just
+ // when the control returns to the main loop.
+ // If the module is unloaded then , KviApp will notice it and will NOT delete the dialog
+ g_pApp->collectGarbage(this);
+
+ // calling dialog.unload here WILL lead to a sigsegv (this is SURE
+ // with a lot of qt versions that have the ugly file dialog "accept before this reference" bug)
+ // to avoid it, we can execute the callback triggered by a timer...
+ // ... umpf ...
+ execute(&params);
+}
+
+
+/*
+ @doc: dialog.image
+ @type:
+ command
+ @title:
+ dialog.image
+ @short:
+ Shows a image dialog
+ @syntax:
+ dialog.image [-b] (<type>,<caption>,<initial_directory>,[<maxsize>,[,<magic1>[,<magic2>[...]]]]]])
+ {
+ <callback_command>
+ }
+ @description:
+ Shows a dialog that allows selecting an [doc:image_id]image_id[doc].
+ The <type> parameter must be a combination of the following flags:<br>
+ 's' : allow selecting from the KVIrc builtin small icons<br>
+ 'f' : allow browsing the local directories<br>
+ 'a' : all of the above<br>
+ The default for <type> is 'a'.<br>
+ <caption> is the caption string for the dialog.<br>
+ <initial_directory> makes sense only if 'f' is specified (if <initial_directory> is empty
+ then the last path used by the image dialog will be used).<br>
+ <maxsize> is the maximum size of the images for that the preview will be generated:
+ this is 256000 bytes by default (if unspecified). Don't make it a lot bigger : it can take a lot to make
+ the thumbnails for bigger images (and it can eat a considerable amount of memory).<br>
+ <magic1>,<magic2>... are the magic parameters: evaluated at dialog.image call time and passed
+ to the <callback_command> as positional parameters.[br]
+ If the -b or -modal switch is specified the dialog will have non-blocking modal behaviour:
+ it will appear above its parent widget and block its input until it's closed.[br]
+ Once the dialog has been shown , the user will select an EXISTING file and click either
+ Ok or Cancel. At this point the dialog is hidden and the <callback_command> is executed passing the selected file(s) as $0
+ and the magic parameters as positional parameters $1 , $2 , $3....[br]
+ If the user clicks "Cancel" or does not select any image the positional parameter $0 will be empty.[br]
+ @examples:
+ [example]
+ dialog.image(f,Choose an image file,/home/pragma/,"256000")
+ {
+ if("$0" != "")run kview $0
+ }
+ [/example]
+*/
+
+//#warning "Examples for these dialogs!"
+
+
+static bool dialog_kvs_cmd_image(KviKvsModuleCallbackCommandCall * c)
+{
+ QString szType,szCaption,szInitialSelection;
+ kvs_uint_t iMaxSize;
+ KviKvsVariantList params;
+
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("mode",KVS_PT_STRING,0,szType)
+ KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption)
+ KVSM_PARAMETER("initial_directory",KVS_PT_STRING,0,szInitialSelection)
+ KVSM_PARAMETER("maxsize",KVS_PT_UINT,KVS_PF_OPTIONAL,iMaxSize)
+ KVSM_PARAMETER("magic",KVS_PT_VARIANTLIST,KVS_PF_OPTIONAL,params)
+ KVSM_PARAMETERS_END(c)
+ bool modal;
+ if(c->hasSwitch('b',"modal")) modal=true;
+ else modal=false;
+ QString szCmd = c->callback()->code();
+
+ int iType = 0;
+
+ if(szType.contains('s'))iType |= KID_TYPE_BUILTIN_IMAGES_SMALL;
+ if(szType.contains('f'))iType |= KID_TYPE_FULL_PATH;
+ if(szType.isEmpty())iType = KID_TYPE_ALL;
+
+ if(iMaxSize < 1)iMaxSize = 256000;
+
+ KviKvsCallbackImageDialog * box = new KviKvsCallbackImageDialog(szCaption,szInitialSelection,iType,iMaxSize,szCmd,&params,c->window(),modal);
+
+ box->show();
+
+ return true;
+}
+
+/*
+ @doc: dialog.yesno
+ @type:
+ function
+ @title:
+ $dialog.yesno
+ @short:
+ Shows a simple yes/no dialog
+ @syntax:
+ $dialog.yesno(<caption:string>,<szText:string>)
+ @description:
+ Shows a simple yes/no dialog. Returns 1 if user clicks "Yes" and 0 if (s)he clicks "No".
+ Please note that this dialog is BLOCKING: it blocks execution of the script
+ until the user has selected either YES or NO.
+ @examples:
+ @seealso:
+*/
+
+static bool dialog_kvs_fnc_yesno(KviKvsModuleFunctionCall * c)
+{
+ QString szCaption;
+ QString szText;
+ KVSM_PARAMETERS_BEGIN(c)
+ KVSM_PARAMETER("caption",KVS_PT_STRING,0,szCaption)
+ KVSM_PARAMETER("text",KVS_PT_STRING,0,szText)
+ KVSM_PARAMETERS_END(c)
+
+ c->enterBlockingSection();
+ bool yes=KviMessageBox::yesNo(szCaption,szText); // this will happily crash on quit ?
+ if(!c->leaveBlockingSection())return true; // just die
+ c->returnValue()->setBoolean(yes);
+ return true;
+}
+
+/*
+
+static int g_iLocalEventLoops = 0;
+
+static bool dialog_module_cmd_unload(KviModule *m,KviCommand *c)
+{
+ // We use local loops in this module: we must FORBID explicit unloading of the
+ // module while local even loops are running
+ ENTER_STACK_FRAME(c,"dialog_module_cmd_unload");
+ c->warning(__tr("The dialog module can't be explicitly unloaded: a modal dialog is currently open"));
+ return c->leaveStackFrame();
+}
+
+static void dialog_module_entering_local_loop(KviModule * m)
+{
+ // Replace unload
+ g_iLocalEventLoops++;
+ if(g_iLocalEventLoops == 1)m->registerCommand("unload",dialog_module_cmd_unload);
+}
+
+static void dialog_module_exiting_local_loop(KviModule * m)
+{
+ g_pModuleManager->registerDefaultCommands(m);
+ g_iLocalEventLoops--;
+}
+
+static bool dialog_module_fnc_textline(KviModule *m,KviCommand *c,KviParameterList * parms,KviStr &buffer)
+{
+ ENTER_STACK_FRAME(c,"dialog_module_fnc_textline");
+
+ KviStr caption = parms->safeFirstParam();
+ KviStr info = parms->safeNextParam();
+ KviStr initial = parms->safeNextParam();
+
+ dialog_module_entering_local_loop(m);
+ QMessageBox::information(0,caption.ptr(),info.ptr(),QMessageBox::Ok);
+ dialog_module_exiting_local_loop(m);
+
+ // It might be that the current window is no longer available!!!
+
+ return c->leaveStackFrame();
+}
+
+*/
+
+/*
+ @doc: noblockingdialogs
+ @type:
+ generic
+ @title:
+ Why there are no blocking dialogs in KVIrc ?
+ @short:
+ Tecnical answer
+ @description:
+ Why there are no blocking dialogs in KVIrc ?[br]
+ The answer is simple: because they're more confusing and tricky than it seems.[br]
+ Blocking the entire program control flow while showing a dialog is
+ rather a bad idea since we have to deal with external entities (servers and other users)
+ that are NOT blocked. This means that the blocking dialogs must block only the
+ script control-flow but let the rest of the application running.
+ Such blocking dialogs actually seem to simplify scripting because
+ the programmer "feels" that the control is always left in the script snippet that he is writing.
+ This is actually confusing: the control IS in the script snippet but while the dialog
+ is open the whole world can change: you can return from the dialog call and discover
+ that the server connection no longer exists and the application is about to quit.[br]
+ This may happen even with non-blocking dialogs ,but in non-blocking mode you have
+ a way to handle this event. Consider the following snippet of code:[br]
+ [example]
+ echo My name is $?
+ [/example]
+ Where $? stands for a blocking input dialog that asks the user for some text.[br]
+ When the input dialog returns the window that the echo was directed to no longer
+ exists and you have no way to stop the echo! (Well...I could add extra code
+ in the executable to handle all these situations but that would be really too expensive).[br]
+ With object scripting this is actually dangerous: you might use a blocking dialog
+ in an object signal handler and when returning discover that this object has been deleted!
+ (The example refers to a simple object , but think about a complex hierarchy of objects
+ where one random gets deleted...).[br]
+ This is why the dialogs in KVIrc are non-blocking :)[br]
+ That's REAL programming.
+*/
+
+
+
+
+
+
+
+static bool dialog_module_init(KviModule * m)
+{
+ g_pDialogModuleDialogList = new KviPointerList<QWidget>;
+ g_pDialogModuleDialogList->setAutoDelete(false);
+
+ KVSM_REGISTER_CALLBACK_COMMAND(m,"message",dialog_kvs_cmd_message);
+ KVSM_REGISTER_CALLBACK_COMMAND(m,"textinput",dialog_kvs_cmd_textinput);
+ KVSM_REGISTER_CALLBACK_COMMAND(m,"file",dialog_kvs_cmd_file);
+ KVSM_REGISTER_CALLBACK_COMMAND(m,"image",dialog_kvs_cmd_image);
+
+ KVSM_REGISTER_FUNCTION(m,"yesno",dialog_kvs_fnc_yesno);
+
+ return true;
+}
+
+static bool dialog_module_cleanup(KviModule *m)
+{
+ // Here we get a tragedy if g_iLocalEventLoops > 0!
+ while(g_pDialogModuleDialogList->first())delete g_pDialogModuleDialogList->first();
+ delete g_pDialogModuleDialogList;
+ g_pDialogModuleDialogList = 0;
+ return true;
+}
+
+static bool dialog_module_can_unload(KviModule *m)
+{
+ return g_pDialogModuleDialogList->isEmpty();
+}
+
+
+KVIRC_MODULE(
+ "KVIrc script dialogs",
+ "1.0.0",
+ "Szymon Stefanek <pragma at kvirc dot net>" ,
+ "Adds the /dialog.* commands functionality\n",
+ dialog_module_init ,
+ dialog_module_can_unload,
+ 0,
+ dialog_module_cleanup
+)
+
+#include "libkvidialog.moc"