2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module dialogs
/*is aliced*/;
22 import arsd
.simpledisplay
;
33 import chibackend
/*: DynStr*/;
34 import receiver
/*: DynStr*/;
37 // ////////////////////////////////////////////////////////////////////////// //
38 public final class HintWindow
: SubWindow
{
39 private DynStr mMessage
;
41 this (const(char)[] amessage
) {
44 int xwdt
= gxTextWidthUtf(amessage
)+6;
45 int xhgt
= gxTextHeightUtf
+4;
46 super(null, GxSize(xwdt
, xhgt
));
47 x0
= screenWidth
-width
;
53 override @property int decorationSizeX () const nothrow @safe @nogc { return 3*2; }
54 override @property int decorationSizeY () const nothrow @safe @nogc { return 2*2; }
56 override @property int clientOffsetX () const nothrow @safe @nogc { return decorationSizeX
/2; }
57 override @property int clientOffsetY () const nothrow @safe @nogc { return decorationSizeY
/2; }
59 @property void message (DynStr v
) {
62 if (x0
== screenWidth
-width
) {
63 width
= gxTextWidthUtf(v
)+6;
64 x0
= screenWidth
-width
;
66 width
= gxTextWidthUtf(v
)+6;
67 if (x0
+width
> screenWidth
) x0
= screenWidth
-width
;
73 override void onPaint () {
76 immutable bool oldNoTitle
= mNoTitle
;
77 scope(exit
) mNoTitle
= oldNoTitle
;
78 if (!minimised
) mNoTitle
= true;
81 if (!minimised
&& mMessage
.length
) {
84 gxClipRect
.shrinkBy(3, 2);
85 gxDrawTextUtf(x0
+3, y0
+2, mMessage
, getColor("text"));
90 // prevent any default keyboard handling
91 override bool onKeySink (KeyEvent event
) {
97 // ////////////////////////////////////////////////////////////////////////// //
98 public final class MessageWindow
: SubWindow
{
99 private DynStr mMessage
;
100 private uint lastBarWidth
;
102 this (const(char)[] amessage
) {
105 int xwdt
= gxTextWidthUtf(amessage
)+decorationSizeX
;
106 int xhgt
= gxTextHeightUtf
+decorationSizeY
;
107 super(null, GxSize(xwdt
, xhgt
));
113 override @property int decorationSizeX () const nothrow @safe @nogc { return 24; }
114 override @property int decorationSizeY () const nothrow @safe @nogc { return 16; }
116 override @property int clientOffsetX () const nothrow @safe @nogc { return decorationSizeX
/2; }
117 override @property int clientOffsetY () const nothrow @safe @nogc { return decorationSizeY
/2; }
119 // returns `true` if need redraw
120 bool setProgress (const(char)[] v
, uint curr
, uint total
) {
125 int xwdt
= gxTextWidthUtf(v
)+decorationSizeX
;
126 int xhgt
= gxTextHeightUtf
+decorationSizeY
;
127 if (xwdt
> width || xhgt
> height
) {
135 if (total
) barWidth
= curr
*cast(uint)(width
-2)/total
;
136 if (barWidth
!= lastBarWidth
) res
= true;
137 lastBarWidth
= barWidth
;
141 override void onPaint () {
144 immutable bool oldNoTitle
= mNoTitle
;
145 scope(exit
) mNoTitle
= oldNoTitle
;
146 if (!minimised
) mNoTitle
= true;
149 if (!minimised
&& mMessage
.length
) {
152 if (lastBarWidth
> 0) {
153 auto rc
= GxRect(x0
+1, y0
+1, lastBarWidth
, height
-2);
154 gxFillRect(rc
, getColor("bar-back"));
157 //gxClipRect.shrinkBy(3, 2);
158 immutable tw
= gxTextWidthUtf(mMessage
);
159 immutable th
= gxTextHeightUtf();
160 gxDrawTextUtf(x0
+(width
-tw
)/2, y0
+(height
-th
)/2, mMessage
, getColor("text"));
165 // prevent any default keyboard handling
166 override bool onKeySink (KeyEvent event
) {
172 // ////////////////////////////////////////////////////////////////////////// //
173 public final class ProgressWindow
: SubWindow
{
174 ProgressBarWidget pbar
;
175 private enum PadX
= 24;
176 private enum PadY
= 8;
178 this (const(char)[] amessage
) {
179 int xwdt
= gxTextWidthUtf(amessage
)+PadX
*2;
180 int xhgt
= gxTextHeightUtf
+PadY
*2;
181 super(null, GxSize(xwdt
, xhgt
));
184 pbar
= new ProgressBarWidget(rootWidget
, amessage
);
185 pbar
.size
= rootWidget
.size
;
191 override @property int decorationSizeX () const nothrow @safe @nogc { return 0; }
192 override @property int decorationSizeY () const nothrow @safe @nogc { return 0; }
194 override @property int clientOffsetX () const nothrow @safe @nogc { return 0; }
195 override @property int clientOffsetY () const nothrow @safe @nogc { return 0; }
197 // returns `true` if need redraw
198 bool setProgress (const(char)[] v
, uint curr
, uint total
) {
201 if (pbar
.text
!= v
) {
203 int xwdt
= gxTextWidthUtf(v
)+PadX
*2;
204 int xhgt
= gxTextHeightUtf
+PadY
*2;
205 if (xwdt
> width || xhgt
> height
) {
206 if (xwdt
< width
) xwdt
= width
;
207 if (xhgt
< height
) xhgt
= height
;
209 rootWidget
.size
= GxSize(xwdt
, xhgt
);
210 pbar
.size
= rootWidget
.size
;
215 if (pbar
.setCurrentTotal(cast(int)curr
, cast(int)total
)) res
= true;
219 // prevent any default keyboard handling
220 override bool onKeySink (KeyEvent event
) {
226 // ////////////////////////////////////////////////////////////////////////// //
227 public class SelectPopBoxWindow
: SubWindow
{
229 void delegate (uint accid
) onSelected
;
232 this (dynstring defacc
) {
235 auto lb
= new SimpleListBoxUDataWidget
!uint(rootWidget
);
238 static auto stat
= LazyStatement
!"Conf"(`
239 SELECT accid AS accid, name AS name, realname AS realname, email AS email
241 WHERE sendserver<>'' AND email<>'' and nntpgroup=''
247 bool accFound
= false;
248 //int defAccIdx = -1;
250 foreach (auto row
; stat
.st
.range
) {
251 dynstring s
= row
.realname
!SQ3Text
;
253 s
~= row
.email
!SQ3Text
;
256 lb
.appendItemWithData(s
, row
.accid
!uint);
257 int w
= gxTextWidthUtf(s
)+2;
258 if (xwdt
< w
) xwdt
= w
;
259 if (defacc
== row
.name
!SQ3Text
) {
260 lb
.curidx
= lb
.length
-1;
263 //if (acc is defaultAcc) defAccIdx = lb.length-1;
264 xhgt
+= gxTextHeightUtf
;
268 if (xhgt
== 0) { super(); return; }
269 if (xhgt
> screenHeight
) xhgt
= screenHeight
-decorationSizeY
;
271 //if (!accFound && defAccIdx >= 0) lb.curidx = defAccIdx;
272 if (xwdt
> screenWidth
-decorationSizeX
) xwdt
= screenWidth
-decorationSizeX
;
274 super("Select Account", GxSize(xwdt
+decorationSizeX
, xhgt
+decorationSizeY
));
275 lb
.width
= clientWidth
;
276 lb
.height
= clientHeight
;
278 lb
.onAction
= delegate (self
) {
279 if (auto acc
= lb
.itemData(lb
.curidx
)) {
281 if (onSelected
!is null) onSelected(acc
); else vbwin
.beep();
294 override bool onKeyBubble (KeyEvent event
) {
296 if (event
== "Escape") { close(); return true; }
297 if (event
== "Enter") {
298 if (auto lb
= querySelector
!Widget("#listbox")) {
304 return super.onKeyBubble(event
);
309 // ////////////////////////////////////////////////////////////////////////// //
310 public class SelectAddressBookWindow
: SubWindow
{
311 static struct Entry
{
317 void delegate (dynstring nick
, dynstring name
, dynstring email
) onSelected
;
319 SimpleListBoxUDataWidget
!Entry lb
;
321 this (const(char)[] prefix
) {
322 static auto stat
= LazyStatement
!"Conf"(`
323 SELECT nick AS nick, name AS name, email AS email
325 WHERE nick<>'' AND email<>''
331 lb
= new SimpleListBoxUDataWidget
!Entry(rootWidget
);
337 foreach (auto row
; stat
.st
.range
) {
338 //conwriteln("! <", row.nick!SQ3Text, "> : <", row.name!SQ3Text, "> : <", row.email!SQ3Text, ">");
340 if (!startsWithCI(row
.nick
!SQ3Text
, prefix
)) continue;
343 if (row
.name
!SQ3Text
.length
) {
344 it
~= row
.name
!SQ3Text
;
346 it
~= row
.email
!SQ3Text
;
349 it
= row
.email
!SQ3Text
;
352 e
.nick
= row
.nick
!SQ3Text
;
353 e
.name
= row
.name
!SQ3Text
;
354 e
.email
= row
.email
!SQ3Text
;
355 lb
.appendItemWithData(it
, e
);
357 int w
= gxTextWidthUtf(it
)+2;
358 if (xwdt
< w
) xwdt
= w
;
359 //if (ae is defae) lb.curidx = lb.length-1;
360 xhgt
+= gxTextHeightUtf
;
363 if (xhgt
== 0) { super(); return; }
364 if (xhgt
> screenHeight
) xhgt
= screenHeight
-decorationSizeY
;
366 if (xwdt
> screenWidth
-decorationSizeX
) xwdt
= screenWidth
-decorationSizeX
;
368 super("Select Recepient", GxSize(xwdt
+decorationSizeX
, xhgt
+decorationSizeY
));
369 lb
.width
= clientWidth
;
370 lb
.height
= clientHeight
;
372 lb
.onAction
= delegate (self
) {
373 Entry ae
= lb
.itemData(lb
.curidx
);
374 if (ae
.email
.length
) {
376 if (onSelected
!is null) onSelected(ae
.nick
, ae
.name
, ae
.email
); else vbwin
.beep();
385 override bool onKeyBubble (KeyEvent event
) {
387 if (event
== "Escape") { close(); return true; }
388 if (event
== "Enter") { lb
.onAction(lb
); return true; }
390 return super.onKeyBubble(event
);
395 // ////////////////////////////////////////////////////////////////////////// //
396 public class PostWindow
: SubWindow
{
402 dynstring references
; // of replyto article
405 bool allowAccountChange
= true;
408 void setFrom (const(char)[] s
) {
409 from
.readonly
= false;
411 from
.readonly
= true;
414 void setFrom (const(char)[] name
, const(char)[] email
) {
428 static bool checkString (const(char)[] s
) nothrow @trusted @nogc {
429 if (s
.length
== 0) return false;
430 if (s
.utflen
> 255) return false;
434 if (!checkString(from
.str)) { from
.focus(); return false; }
435 if (!nntp
&& !checkString(to
.str)) { to
.focus(); return false; }
436 if (!checkString(subj
.str)) { subj
.focus(); return false; }
437 if (ed
.editor
[].length
== 0) { ed
.focus(); return false; }
439 static const(char)[] extractMail (const(char)[] s
) nothrow @trusted @nogc {
441 if (s
.length
== 0 || s
[$-1] != '>') return s
;
442 auto spp
= s
.lastIndexOf('<');
443 if (spp
< 0) return s
;
444 s
= s
[spp
+1..$-1].xstrip
;
448 static const(char)[] extractName (const(char)[] s
) nothrow @trusted @nogc {
450 if (s
.length
== 0 || s
[$-1] != '>') return null;
451 auto spp
= s
.lastIndexOf('<');
452 if (spp
< 0) return null;
458 if (!chiroGetAccountInfo(accname
.getData
, out acc
)) return false;
460 if (nntp
!= (acc
.nntpgroup
.length
!= 0)) return false;
463 conwriteln("ACCOUNT ID: ", acc.accid);
464 conwriteln("ACCOUNT NAME: ", acc.name);
465 conwriteln("ACCOUNT REAL NAME: ", acc.realname);
466 conwriteln("ACCOUNT EMAIL: ", acc.email);
467 conwriteln("ACCOUNT NNTP GROUP: ", acc.nntpgroup);
470 dynstring fromname
= extractName(from
.str);
471 dynstring frommail
= extractMail(from
.str);
473 dynstring toname
= extractName(to
.str);
474 dynstring tomail
= extractMail(to
.str);
476 conwriteln("FROM: name=<", fromname
, ">:<", strEncodeQ(fromname
), "> : mail=<", frommail
, ">");
477 conwriteln("TO: name=<", toname
, ">:<", strEncodeQ(toname
), "> : mail=<", tomail
, ">");
479 if (!isGoodEmail(frommail
)) { from
.focus(); return false; }
480 if (!nntp
&& !isGoodEmail(tomail
)) { to
.focus(); return false; }
482 // build reply article and add it to send queue
484 ed
.editor
.clearAndDisableUndo(); // so removing attaches will not add 'em to undo, lol
485 dynstring
[] attnames
= ed
.extractAttaches();
486 if (attnames
.length
) foreach (dynstring ss
; attnames
) conwriteln("ATTACH: ", ss
);
489 msg
.setFromName(fromname
);
490 msg
.setFromMail(frommail
);
491 msg
.setToName(toname
);
492 msg
.setToMail(tomail
);
493 if (acc
.nntpgroup
.length
) msg
.setNewsgroup(acc
.nntpgroup
);
494 msg
.setSubj(subj
.str);
495 msg
.setBody(ed
.getText
);
497 //if (replyto.length) msg.appendReference(replyto);
499 const(char)[] refs
= references
.xstrip
;
500 while (refs
.length
) {
502 while (spp
< refs
.length
&& refs
[spp
] > ' ') ++spp
;
503 msg
.appendReference(refs
[0..spp
]);
504 refs
= refs
[spp
..$].xstrip
;
507 foreach (dynstring ss
; attnames
) {
510 } catch (Exception e
) {
511 conwriteln("ERROR: cannot attach file '", ss
, "'!");
515 // clear editor, so it will free used memory
516 ed
.editor
.clearAndDisableUndo();
519 bool skipFilters
= true;
526 if (desttag
.length
) {
529 } else if (acc
.inbox
.length
) {
538 //conwriteln("TAGS: ", tags);
541 dynstring mdata
= msg
.getPrepared
;
543 // for NNTP, we will do the trick: insert deleted message into the storage
544 // this is because next NNTP check will receive it
546 uid INTEGER PRIMARY KEY /* the same as in the storage, not automatic */
547 , accid INTEGER /* account from which this message should be sent */
548 , from_pop3 TEXT /* "from" for POP3 */
549 , to_pop3 TEXT /* "to" for POP3 */
550 , data TEXT /* PACKED data to send */
551 , sendtime INTEGER DEFAULT 0 /* 0: not yet; unixtime */
552 , lastsendtime INTEGER DEFAULT 0 /* when we last tried to send it? 0 means "not yet" */
555 // insert into main store
558 foreach (auto row
; dbStore
.statement(`
559 INSERT INTO messages(tags, data) VALUES(:tags, ChiroPack(:data)) RETURNING uid;`)
560 .bindConstText(":tags", tags
.getData
)
561 .bindConstBlob(":data", mdata
.getData
)
568 if (nntp
) tomail
.clear();
570 // insert into unsent queue
574 ( uid, accid, from_pop3, to_pop3, data)
575 VALUES(:uid,:accid,:from_pop3,:to_pop3,ChiroPack(:data))
578 .bind(":accid", acc
.accid
)
579 .bind(":accid", acc
.accid
)
580 .bindConstText(":from_pop3", frommail
.getData
)
581 .bindConstText(":to_pop3", tomail
.getData
)
582 .bindConstBlob(":data", mdata
.getData
)
586 conwriteln("message inserted");
588 updateViewDB(skipFilters
:skipFilters
);
592 conwriteln("=======================");
593 conwrite(msg.getPrepared);
594 conwriteln("-----------------------");
600 override void createWidgets () {
601 (new VBoxWidget
).enter{
602 (new HBoxWidget
).enter{
603 with (new HotLabelWidget("&From:", LabelWidget
.HAlign
.Right
)) { width
= width
+2; hsizeId
= "editors"; }
605 from
= new LineEditWidget();
607 from
.readonly
= true;
611 (new HBoxWidget
).enter{
612 with (new HotLabelWidget("&To:", LabelWidget
.HAlign
.Right
)) { width
= width
+2; hsizeId
= "editors"; }
614 to
= new LineEditWidget();
619 (new HBoxWidget
).enter{
620 with (new HotLabelWidget("&Subj:", LabelWidget
.HAlign
.Right
)) { width
= width
+2; hsizeId
= "editors"; }
622 subj
= new LineEditWidget();
627 (new VBoxWidget
).enter{
628 ed
= new EditorWidget();
633 (new HBoxWidget
).enter{
634 new SpacerWidget(12);
635 //new SpringWidget(1);
636 with (new ButtonWidget(" Send ")) {
637 hsizeId
= "okcancel";
638 //deftype = Default.Accept;
639 onAction
= delegate (self
) {
640 if (trySend
) close(); else vbwin
.beep();
644 new SpacerWidget(12);
645 with (new ButtonWidget(" Cancel ")) {
646 hsizeId
= "okcancel";
647 //deftype = Default.Cancel;
648 onAction
= delegate (self
) {
653 //new SpringWidget(1);
654 new SpacerWidget(12);
658 relayout(); // don't resize window
663 int wanthgt
= screenHeight
-42*2;
664 if (wanthgt
< 80) wanthgt
= 80;
665 int wantwdt
= screenWidth
-64*2;
666 if (wantwdt
< 506) wantwdt
= 506;
667 super("Compose Mail", GxSize(wantwdt
, wanthgt
));
668 //if (hasWindowClass(this)) return;
671 override bool onKeySink (KeyEvent event
) {
673 if (event
== "Escape" && !ed
.editor
.textChanged
) { close(); return true; }
674 if (event
== "C-G" || event
== "C-C") {
675 if (ed
.editor
.textChanged
) {
676 auto qww
= new YesNoWindow("Close?", "Do you really want to close the editor?", true);
677 qww
.onYes
= () { close(); };
686 if (event == "M-Tab" && focusedWidget is to) {
687 auto ae = abookFindByNick(to.str);
688 //if (ae is null) ae = abookFindByMail(to.str);
690 if (ae.realname.length) to.str = ae.realname~" <"~ae.mail~">"; else to.str = ae.mail;
698 // select destination from the address book
699 if (event
== "C-Space" && focusedWidget
is to
) {
700 auto wae
= new SelectAddressBookWindow(to
.str);
701 if (wae
.lb
.length
!= 0) {
702 wae
.onSelected
= delegate (dynstring nick
, dynstring name
, dynstring email
) {
703 if (name
.length
) to
.str = name
~" <"~email
~">"; else to
.str = email
;
711 // select from account from the address book
712 if (event
== "C-Space" && focusedWidget
is from
) {
713 if (allowAccountChange
) {
714 auto wacc
= new SelectPopBoxWindow(accname
);
715 wacc
.onSelected
= delegate (uint accid
) {
717 if (chiroGetAccountInfo(accid
, out acc
)) {
720 conwriteln("ACCOUNT ID: ", acc.accid);
721 conwriteln("ACCOUNT NAME: ", acc.name);
722 conwriteln("ACCOUNT REAL NAME: ", acc.realname);
723 conwriteln("ACCOUNT EMAIL: ", acc.email);
724 conwriteln("ACCOUNT NNTP GROUP: ", acc.nntpgroup);
726 setFrom(acc
.realname
~" <"~acc
.email
~">");
733 if (event
== "C-Enter") {
734 auto qww
= new YesNoWindow("Send?", "Do you really want to send the message?", true);
736 if (trySend
) close(); else vbwin
.beep();
741 return super.onKeyBubble(event
);
746 // ////////////////////////////////////////////////////////////////////////// //
747 public class TitlerWindow
: SubWindow
{
748 LineEditWidget edtTitle
;
749 LineEditWidget fromName
;
750 LineEditWidget fromMail
;
751 //LineEditWidget fromTag;
757 bool delegate (const(char)[] name
, const(char)[] mail
, const(char)[] folder
, const(char)[] title
) onSelected
;
759 override void createWidgets () {
760 new SpacerWidget(rootWidget
, 2);
763 fromName
= new LineEditWidget(rootWidget
, "Name:");
766 new SpacerWidget(rootWidget
, 2);
767 fromMail
= new LineEditWidget(rootWidget
, "Mail:");
770 new SpacerWidget(rootWidget
, 2);
771 edtTitle
= new LineEditWidget(rootWidget
, "Title:");
774 (new HBoxWidget
).enter{
775 with (new HotLabelWidget("&Name:", LabelWidget
.HAlign
.Right
)) { width
= width
+2; hsizeId
= "editors"; }
777 fromName
= new LineEditWidget();
782 (new HBoxWidget
).enter{
783 with (new HotLabelWidget("&Mail:", LabelWidget
.HAlign
.Right
)) { width
= width
+2; hsizeId
= "editors"; }
785 fromMail
= new LineEditWidget();
790 (new HBoxWidget
).enter{
791 with (new HotLabelWidget("&Title:", LabelWidget
.HAlign
.Right
)) { width
= width
+2; hsizeId
= "editors"; }
793 edtTitle
= new LineEditWidget();
799 (new HBoxWidget
).enter{
802 with (new ButtonWidget(" O&k ")) {
803 hsizeId
= "okcancel";
804 deftype
= Default
.Accept
;
805 onAction
= delegate (self
) {
806 if (onSelected
!is null) {
807 if (!onSelected(fromName
.str, fromMail
.str, folder
, edtTitle
.str)) return;
813 with (new ButtonWidget(" Cancel ")) {
814 hsizeId
= "okcancel";
815 deftype
= Default
.Cancel
;
816 onAction
= delegate (self
) {
827 edtTitle
.str = title
;
837 this (const(char)[] aname
, const(char)[] amail
, const(char)[] afolder
, const(char)[] atitle
) {
843 DynStr caption
= "Title for ";
848 super(caption
.getData
);
853 // ////////////////////////////////////////////////////////////////////////// //
854 public class TagOptionsWindow
: SubWindow
{
855 LabelWidget optPath
; // real path
856 LineEditWidget optMonthes
;
857 CheckboxWidget optThreaded
;
858 CheckboxWidget optAttaches
;
861 void delegate (const(char)[] tagname
) onUpdated
;
866 auto vv
= optMonthes
.str.xstrip
;
867 if (vv
.length
== 0) {
871 if (mv
< -1) mv
= -666; else if (mv
== 0) mv
= -1;
873 } catch (Exception
) {
876 if (mv
< -2) return false;
877 import core
.stdc
.stdio
: snprintf
;
878 char[1024] xname
= void;
879 const(char)[] tn
= tagname
.getData
;
880 auto xlen
= snprintf(xname
.ptr
, xname
.sizeof
, "/mainpane/msgview/monthlimit%s%.*s",
881 (tn
.length
&& tn
[0] != '/' ?
"/".ptr
: "".ptr
), cast(uint)tn
.length
, tn
.ptr
);
884 if (xname
[0..xlen
] != "/mainpane/msgview/monthlimit") {
885 chiroDeleteOption(xname
[0..xlen
]);
889 chiroSetOption(xname
[0..xlen
], mv
);
891 // fix threading and attaches
892 if (optThreaded
.enabled
) {
895 SET threading=:trd, noattaches=:noatt
898 .bindConstText(":name", tagname
.getData())
899 .bind(":trd", (optThreaded
.checked ?
1 : 0))
900 .bind(":noatt", (optAttaches
.checked ?
0 : 1))
903 if (onUpdated
!is null) onUpdated(tagname
.getData
);
907 override void createWidgets () {
908 optPath
= new LabelWidget(rootWidget
, "", LabelWidget
.HAlign
.Center
);
912 optMonthes
= new LineEditWidget(rootWidget
, "Monthes:");
914 optMonthes
.width
= optMonthes
.titwdt
+64;
916 (new HBoxWidget
).enter{
917 with (new HotLabelWidget("&Monthes:", LabelWidget
.HAlign
.Right
)) { width
= width
+2; /*hsizeId = "editors";*/ }
919 optMonthes
= new LineEditWidget();
920 //optMonthes.flex = 1;
921 optMonthes
.width
= gxTextWidthUtf("96669");
922 //new SpringWidget(1);
926 optThreaded
= new CheckboxWidget(rootWidget
, "&Threaded");
927 optThreaded
.flex
= 1;
929 optAttaches
= new CheckboxWidget(rootWidget
, "&Attaches");
930 optAttaches
.flex
= 1;
933 (new HBoxWidget
).enter{
936 with (new ButtonWidget(" O&k ")) {
937 hsizeId
= "okcancel";
938 deftype
= Default
.Accept
;
939 onAction
= delegate (self
) {
940 if (onAccept()) close();
944 with (new ButtonWidget(" Cancel ")) {
945 hsizeId
= "okcancel";
946 deftype
= Default
.Cancel
;
947 onAction
= delegate (self
) {
958 immutable bool goodTag
= (chiroGetTagUid(tagname
.getData
) != 0);
960 import std
.conv
: to
;
962 DynStr path
= chiroGetTagMonthLimitEx(tagname
.getData
, out val
, defval
:6);
963 //conwriteln("TAGNAME=<", tagname.getData, ">; val=", val, "; path=<", path.getData, ">");
964 optPath
.text
= path
.getData
;
965 optMonthes
.str = val
.to
!string
;
966 optPath
.width
= gxTextWidthUtf(optPath
.text
)+4;
970 foreach (auto row
; dbView
.statement(`
971 SELECT threading AS trd, noattaches AS noatt FROM tagnames WHERE tag=:tag LIMIT 1
972 ;`).bindConstText(":tag", tagname
.getData
).range
)
974 optThreaded
.checked
= (row
.trd
!int == 1);
975 optAttaches
.checked
= (row
.noatt
!int == 0);
978 optThreaded
.enabled
= false;
979 optAttaches
.enabled
= false;
982 optMonthes
.killTextOnChar
= true;
984 minWinSize
.w
= optPath
.width
;
990 this (const(char)[] atagname
) {
993 DynStr caption
= "options for '";
996 super(caption
.getData
);