[gnome-commander/treeview] Added TreeView widget for tree navigation
- From: Piotr Eljasiak <epiotr src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-commander/treeview] Added TreeView widget for tree navigation
- Date: Tue, 10 Aug 2010 23:11:26 +0000 (UTC)
commit 5dbf6cfda7230b402843e36f2d2444650b31ae59
Author: Guillaume Wardavoir <earlgrey free fr>
Date: Wed Aug 11 01:09:05 2010 +0200
Added TreeView widget for tree navigation
pixmaps/file-type-icons/Makefile.am | 7 +
pixmaps/file-type-icons/file_type_dir_green.xpm | 46 +
pixmaps/file-type-icons/file_type_dir_orange.xpm | 46 +
pixmaps/file-type-icons/file_type_dir_red.xpm | 46 +
.../file_type_symlink_to_dir_green.xpm | 163 ++++
.../file_type_symlink_to_dir_orange.xpm | 152 ++++
.../file_type_symlink_to_dir_red.xpm | 158 ++++
pixmaps/file-type-icons/file_type_unknown.xpm | 42 +
src/Makefile.am | 6 +
src/gnome-cmd-foldview-control.cc | 905 ++++++++++++++++++++
src/gnome-cmd-foldview-gvfs.cc | 731 ++++++++++++++++
src/gnome-cmd-foldview-gvfs.h | 335 ++++++++
src/gnome-cmd-foldview-model.cc | 447 ++++++++++
src/gnome-cmd-foldview-private.h | 788 +++++++++++++++++
src/gnome-cmd-foldview-view.cc | 701 +++++++++++++++
src/gnome-cmd-foldview.cc | 380 ++++++++
src/gnome-cmd-foldview.h | 40 +
src/gnome-cmd-main-menu.cc | 11 +-
src/gnome-cmd-main-win.cc | 99 ++-
src/gnome-cmd-main-win.h | 3 +
src/gnome-cmd-style.cc | 86 ++
src/gnome-cmd-style.h | 2 +
src/gnome-cmd-user-actions.cc | 10 +
src/gnome-cmd-user-actions.h | 1 +
24 files changed, 5198 insertions(+), 7 deletions(-)
---
diff --git a/pixmaps/file-type-icons/Makefile.am b/pixmaps/file-type-icons/Makefile.am
index 3ad607d..2d3106e 100644
--- a/pixmaps/file-type-icons/Makefile.am
+++ b/pixmaps/file-type-icons/Makefile.am
@@ -3,6 +3,13 @@
pixmapsdir = $(datadir)/pixmaps/@PACKAGE@/file-type-icons
pixmaps_DATA = \
file_type_dir.xpm \
+ file_type_dir_green.xpm \
+ file_type_dir_orange.xpm \
+ file_type_dir_red.xpm \
+ file_type_symlink_to_dir_green.xpm \
+ file_type_symlink_to_dir_orange.xpm \
+ file_type_symlink_to_dir_red.xpm \
+ file_type_unknown.xpm \
file_type_socket.xpm \
file_type_block_device.xpm \
file_type_fifo.xpm \
diff --git a/pixmaps/file-type-icons/file_type_dir_green.xpm b/pixmaps/file-type-icons/file_type_dir_green.xpm
new file mode 100644
index 0000000..664537e
--- /dev/null
+++ b/pixmaps/file-type-icons/file_type_dir_green.xpm
@@ -0,0 +1,46 @@
+/* XPM */
+static char * file_type_dir_green_xpm[] = {
+"16 16 27 1",
+" c None",
+". c #000000",
+"+ c #7FD77F",
+"@ c #64BC64",
+"# c #63C163",
+"$ c #52AA5E",
+"% c #DFF7D5",
+"& c #BEF0BC",
+"* c #DCF8DE",
+"= c #9AE0A0",
+"- c #B7EBC4",
+"; c #B2EEAA",
+"> c #9AE189",
+", c #A6EB93",
+"' c #8FDA80",
+") c #7FD37F",
+"! c #6CC46C",
+"~ c #CEF4C8",
+"{ c #54925D",
+"] c #4D835B",
+"^ c #6DC96D",
+"/ c #5BB95B",
+"( c #81D476",
+"_ c #5DB35D",
+": c #47714B",
+"< c #B2EC9E",
+"[ c #3C6446",
+" ",
+" ",
+" .... ",
+" + +@. ",
+" .#$#$#$...... ",
+" .%&*&*&%*=-;>. ",
+" .;+,+,+,')!+$. ",
+" .~,+,+,))!+!{. ",
+" .;+,+,)+!+!!]. ",
+" .~,+,)+!+!^/]. ",
+" .;+,(+!+!!/_:. ",
+" .~,(+!+!!__$:. ",
+" .<{${_{${]::[. ",
+" ............ ",
+" ",
+" "};
diff --git a/pixmaps/file-type-icons/file_type_dir_orange.xpm b/pixmaps/file-type-icons/file_type_dir_orange.xpm
new file mode 100644
index 0000000..df12ede
--- /dev/null
+++ b/pixmaps/file-type-icons/file_type_dir_orange.xpm
@@ -0,0 +1,46 @@
+/* XPM */
+static char * file_type_dir_orange_xpm[] = {
+"16 16 27 1",
+" c None",
+". c #000000",
+"+ c #FFA657",
+"@ c #FF7A21",
+"# c #FF8125",
+"$ c #F0620C",
+"% c #FFE5CD",
+"& c #FFD2AD",
+"* c #FFE7D5",
+"= c #FFAD7B",
+"- c #FFB9A3",
+"; c #FFD099",
+"> c #FFB46B",
+", c #FFC77F",
+"' c #FFAC5B",
+") c #FF9C53",
+"! c #FF8331",
+"~ c #FFDFBD",
+"{ c #D54811",
+"] c #AE4922",
+"^ c #FF9037",
+"/ c #FF7815",
+"( c #FFA04B",
+"_ c #FF6B11",
+": c #A64312",
+"< c #FFCD8B",
+"[ c #8E3512",
+" ",
+" ",
+" .... ",
+" + +@. ",
+" .#$#$#$...... ",
+" .%&*&*&%*=-;>. ",
+" .;+,+,+,')!+$. ",
+" .~,+,+,))!+!{. ",
+" .;+,+,)+!+!!]. ",
+" .~,+,)+!+!^/]. ",
+" .;+,(+!+!!/_:. ",
+" .~,(+!+!!__$:. ",
+" .<{${_{${]::[. ",
+" ............ ",
+" ",
+" "};
diff --git a/pixmaps/file-type-icons/file_type_dir_red.xpm b/pixmaps/file-type-icons/file_type_dir_red.xpm
new file mode 100644
index 0000000..3fa6faa
--- /dev/null
+++ b/pixmaps/file-type-icons/file_type_dir_red.xpm
@@ -0,0 +1,46 @@
+/* XPM */
+static char * file_type_dir_red_xpm[] = {
+"16 16 27 1",
+" c None",
+". c #000000",
+"+ c #D21224",
+"@ c #AC1426",
+"# c #AE1422",
+"$ c #901829",
+"% c #EE4662",
+"& c #ED3147",
+"* c #EE4A69",
+"= c #E81432",
+"- c #EC2C55",
+"; c #EC2432",
+"> c #DF1322",
+", c #EB151F",
+"' c #D51320",
+") c #D01228",
+"! c #BA1024",
+"~ c #ED3B50",
+"{ c #881226",
+"] c #7D0D22",
+"^ c #BE1021",
+"/ c #A11727",
+"( c #CB111E",
+"_ c #9F1727",
+": c #71091D",
+"< c #EB1D26",
+"[ c #62081D",
+" ",
+" ",
+" .... ",
+" + +@. ",
+" .#$#$#$...... ",
+" .%&*&*&%*=-;>. ",
+" .;+,+,+,')!+$. ",
+" .~,+,+,))!+!{. ",
+" .;+,+,)+!+!!]. ",
+" .~,+,)+!+!^/]. ",
+" .;+,(+!+!!/_:. ",
+" .~,(+!+!!__$:. ",
+" .<{${_{${]::[. ",
+" ............ ",
+" ",
+" "};
diff --git a/pixmaps/file-type-icons/file_type_symlink_to_dir_green.xpm b/pixmaps/file-type-icons/file_type_symlink_to_dir_green.xpm
new file mode 100644
index 0000000..884da12
--- /dev/null
+++ b/pixmaps/file-type-icons/file_type_symlink_to_dir_green.xpm
@@ -0,0 +1,163 @@
+/* XPM */
+static char * file_type_symlink_to_dir_green_xpm[] = {
+"16 16 144 2",
+" c None",
+". c #33D53E",
+"+ c #289A3E",
+"@ c #3EF843",
+"# c #4DDB61",
+"$ c #269026",
+"% c #58E34D",
+"& c #CAFFAF",
+"* c #3CF44D",
+"= c #0CB02B",
+"- c #3FC743",
+"; c #CBFEBC",
+"> c #D6FFC1",
+", c #38E641",
+"' c #089E13",
+") c #45F555",
+"! c #55D852",
+"~ c #4EE659",
+"{ c #3AE63A",
+"] c #2EE633",
+"^ c #40F85F",
+"/ c #54E665",
+"( c #4DBE44",
+"_ c #91F57D",
+": c #A7FF8F",
+"< c #A9FE9E",
+"[ c #56E470",
+"} c #07B935",
+"| c #75F187",
+"1 c #E2FFD7",
+"2 c #F7FFF3",
+"3 c #F7FFED",
+"4 c #F7FCEC",
+"5 c #E6FFD9",
+"6 c #EFFDE9",
+"7 c #CEF6C0",
+"8 c #70FE62",
+"9 c #4DF840",
+"0 c #8CF57B",
+"a c #90FC84",
+"b c #24E024",
+"c c #22B23D",
+"d c #3EE43E",
+"e c #B6FF99",
+"f c #95FD87",
+"g c #8BF472",
+"h c #8CFE7A",
+"i c #80EB5B",
+"j c #8AE66A",
+"k c #7EF86E",
+"l c #5BFF53",
+"m c #55FF51",
+"n c #4CDB45",
+"o c #61DE50",
+"p c #74FE5E",
+"q c #22E23D",
+"r c #37CB64",
+"s c #35DB39",
+"t c #A5FF8D",
+"u c #8BFB7F",
+"v c #86FA72",
+"w c #7CF96B",
+"x c #6DFE6A",
+"y c #55FF55",
+"z c #4DFD4D",
+"A c #53F94F",
+"B c #4BF842",
+"C c #2BF826",
+"D c #1CF311",
+"E c #27FE1C",
+"F c #7FFE6A",
+"G c #27DB38",
+"H c #27BD51",
+"I c #37E550",
+"J c #9BFF8D",
+"K c #83FF83",
+"L c #74FE6E",
+"M c #5EFA61",
+"N c #6BE55F",
+"O c #63E555",
+"P c #54E440",
+"Q c #44EC32",
+"R c #2AE820",
+"S c #28F228",
+"T c #1DEB27",
+"U c #12E626",
+"V c #41FF53",
+"W c #59FB55",
+"X c #1FB940",
+"Y c #21E126",
+"Z c #82FA6E",
+"` c #6AF15F",
+" . c #67F054",
+".. c #63F957",
+"+. c #45FF31",
+"@. c #3CFF2D",
+"#. c #30F426",
+"$. c #25E71B",
+"%. c #1FE81A",
+"&. c #15E410",
+"*. c #09E709",
+"=. c #00EA00",
+"-. c #1CD036",
+";. c #1DCB4E",
+">. c #19D919",
+",. c #82FE6A",
+"'. c #71FE5E",
+"). c #58FE42",
+"!. c #46FB39",
+"~. c #48E844",
+"{. c #27F127",
+"]. c #1EFC1E",
+"^. c #0EE613",
+"/. c #0FED19",
+"(. c #00F017",
+"_. c #0EFE2B",
+":. c #0ADA27",
+"<. c #1BC337",
+"[. c #37B151",
+"}. c #0EB431",
+"|. c #0FCD37",
+"1. c #05CF2B",
+"2. c #05D32C",
+"3. c #2ABC5A",
+"4. c #17AF37",
+"5. c #00D819",
+"6. c #00EA06",
+"7. c #00EA0B",
+"8. c #23FB2E",
+"9. c #04B600",
+"0. c #1AD23D",
+"a. c #00AE1D",
+"b. c #09F720",
+"c. c #2DDD1F",
+"d. c #03D721",
+"e. c #26CC4D",
+"f. c #009411",
+"g. c #35FF3F",
+"h. c #0DDD2F",
+"i. c #2CBC47",
+"j. c #00AE19",
+"k. c #06E826",
+"l. c #129C29",
+"m. c #13B732",
+" . + ",
+" @ # $ ",
+" % & * = ",
+" - ; > , ' ",
+") ! ~ { ] ^ / ( _ : < [ } ",
+"| 1 2 3 4 5 6 7 8 9 0 a b c ",
+"d e f g h i j k l m n o p q r ",
+"s t u v w x y z A B C D E F G H ",
+"I J K L M N O P Q R S T U V W X ",
+"Y Z ` + # $ % &.*.=.-.;. ",
+">.,.'.).!.~.{.].^./.(._.:.<. ",
+"[.}.|.1.2.3.4.5.6.7.8.9.0. ",
+" a.b.c.d.e. ",
+" f.g.h.i. ",
+" j.k.l. ",
+" m.f. "};
diff --git a/pixmaps/file-type-icons/file_type_symlink_to_dir_orange.xpm b/pixmaps/file-type-icons/file_type_symlink_to_dir_orange.xpm
new file mode 100644
index 0000000..e314a53
--- /dev/null
+++ b/pixmaps/file-type-icons/file_type_symlink_to_dir_orange.xpm
@@ -0,0 +1,152 @@
+/* XPM */
+static char * file_type_symlink_to_dir_orange_xpm[] = {
+"16 16 133 2",
+" c None",
+". c #FF8E43",
+"+ c #FF910F",
+"@ c #FF9B65",
+"# c #FFA85B",
+"$ c #FF5907",
+"% c #FF8A61",
+"& c #FFBFBF",
+"* c #FFA461",
+"= c #FF8F0B",
+"- c #FF8441",
+"; c #FFCEC9",
+"> c #FFCDCD",
+", c #FF9453",
+"' c #FA6400",
+") c #FFA969",
+"! c #FF8F5D",
+"~ c #FFA163",
+"{ c #FF8D55",
+"] c #FF8B4B",
+"^ c #FFB667",
+"/ c #FFAC69",
+"( c #FF713F",
+"_ c #FFA593",
+": c #FFB1A7",
+"< c #FFC2B1",
+"[ c #FFBA69",
+"} c #FFA20F",
+"| c #FFC189",
+"1 c #FFDFDD",
+"2 c #FFF3F3",
+"3 c #FFEDF1",
+"4 c #FFEBF2",
+"5 c #FFDFDF",
+"6 c #FFEAE9",
+"7 c #FFC9C5",
+"8 c #FFA285",
+"9 c #FF8E67",
+"0 c #FFA691",
+"a c #FFB49D",
+"b c #FF7E3F",
+"c c #FF971D",
+"d c #FF8E57",
+"e c #FFB3AF",
+"f c #FFB39F",
+"g c #FF9A89",
+"h c #FFAB97",
+"i c #FF7B71",
+"j c #FF8279",
+"k c #FFA289",
+"l c #FFA07B",
+"m c #FFA279",
+"n c #FF8555",
+"o c #FF815F",
+"p c #FF9981",
+"q c #FF993F",
+"r c #FFBD3F",
+"s c #FF8949",
+"t c #FFB0A5",
+"u c #FFB199",
+"v c #FFA28D",
+"w c #FFA087",
+"x c #FFAE8B",
+"y c #FFA67B",
+"z c #FFA275",
+"A c #FF9E73",
+"B c #FF9369",
+"C c #FF8853",
+"D c #FF753F",
+"E c #FF8251",
+"F c #FFA18B",
+"G c #FF903F",
+"H c #FFB129",
+"I c #FFA351",
+"J c #FFB8A5",
+"K c #FFBF9F",
+"L c #FFAD8D",
+"M c #FFAC7F",
+"N c #FF916F",
+"O c #FF8C69",
+"P c #FF7B57",
+"Q c #FF7B53",
+"R c #FF7843",
+"S c #FF8A51",
+"T c #FF8A43",
+"U c #FF8D39",
+"V c #FFAB6D",
+"W c #FF9E21",
+"X c #FF833F",
+"Y c #FF9C79",
+"Z c #FF8D6F",
+"` c #FF8661",
+" . c #FF875D",
+".. c #FF7A3F",
+"+. c #FF7335",
+"@. c #FF7633",
+"#. c #FF722D",
+"$. c #FF912F",
+"%. c #FFB22D",
+"&. c #FF9E8B",
+"*. c #FF9C81",
+"=. c #FF8C6D",
+"-. c #FF8B63",
+";. c #FF894F",
+">. c #FF7C35",
+",. c #FF853B",
+"'. c #FF8933",
+"). c #FF9845",
+"!. c #FF8E29",
+"~. c #FF9625",
+"{. c #FFA42D",
+"]. c #FF970F",
+"^. c #FF9F23",
+"/. c #FF9921",
+"(. c #FFBC2B",
+"_. c #FF9813",
+":. c #FF8421",
+"<. c #FF772D",
+"[. c #FF7C2D",
+"}. c #FF5307",
+"|. c #FFA02F",
+"1. c #FF8401",
+"2. c #FF8F3D",
+"3. c #FF6E3B",
+"4. c #FF8921",
+"5. c #FFAB33",
+"6. c #EC6A00",
+"7. c #FF9E63",
+"8. c #FF9A2D",
+"9. c #FF9F2D",
+"0. c #FF7F01",
+"a. c #FF9231",
+"b. c #FF9415",
+" . + ",
+" @ # $ ",
+" % & * = ",
+" - ; > , ' ",
+") ! ~ { ] ^ / ( _ : < [ } ",
+"| 1 2 3 4 5 6 7 8 9 0 a b c ",
+"d e f g h i j k l m n o p q r ",
+"s t u v w x y z A B C D E F G H ",
+"I J K L M N O P Q R S T U V m W ",
+"X F Y Z Y ` .E D + # $ % ",
+"@.&.*.=.-.! ;.S >.,.'.).!.~. ",
+"{.].^.c /.(._.:.<.[., }.|. ",
+" 1.2.3.4.5. ",
+" 6.7.8.9. ",
+" 0.a.1. ",
+" b.6. "};
diff --git a/pixmaps/file-type-icons/file_type_symlink_to_dir_red.xpm b/pixmaps/file-type-icons/file_type_symlink_to_dir_red.xpm
new file mode 100644
index 0000000..71f8ded
--- /dev/null
+++ b/pixmaps/file-type-icons/file_type_symlink_to_dir_red.xpm
@@ -0,0 +1,158 @@
+/* XPM */
+static char * file_type_symlink_to_dir_red_xpm[] = {
+"16 16 139 2",
+" c None",
+". c #E02A1C",
+"+ c #9E371C",
+"@ c #FF2E29",
+"# c #E74E35",
+"$ c #941A1A",
+"% c #F03441",
+"& c #FF9DBD",
+"* c #FF3A25",
+"= c #B42600",
+"- c #CE2F2C",
+"; c #FFA9BD",
+"> c #FFAFC9",
+", c #F6261C",
+"' c #9E0B00",
+") c #FF412D",
+"! c #E33B3F",
+"~ c #F44032",
+"{ c #F61E1E",
+"] c #F71611",
+"^ c #FF532B",
+"/ c #F34F39",
+"( c #C2343E",
+"_ c #FF637D",
+": c #FF7F9A",
+"< c #FF8B99",
+"[ c #F1623B",
+"} c #B83400",
+"| c #FC715A",
+"1 c #FFC3D4",
+"2 c #FFDFEA",
+"3 c #FFD9EE",
+"4 c #FBD9F0",
+"5 c #FFC5D9",
+"6 c #FED4E1",
+"7 c #FAAABF",
+"8 c #FF5363",
+"9 c #FF2B3A",
+"0 c #FF6177",
+"a c #FF717E",
+"b c #EB0D0D",
+"c c #B73613",
+"d c #F32323",
+"e c #FF89AA",
+"f c #FF7585",
+"g c #FF5777",
+"h c #FF697E",
+"i c #F84070",
+"j c #F1517B",
+"k c #FF576B",
+"l c #FF454E",
+"m c #FF4347",
+"n c #E82C35",
+"o c #EA384D",
+"p c #FF4F68",
+"q c #ED2B0B",
+"r c #D15E25",
+"s c #E91F1B",
+"t c #FF7D99",
+"u c #FF6B79",
+"v c #FF5D74",
+"w c #FF595D",
+"x c #FF4747",
+"y c #FF3D3D",
+"z c #FF3B40",
+"A c #FF2D37",
+"B c #FF1319",
+"C c #F8000C",
+"D c #FF0F1A",
+"E c #FF5970",
+"F c #E32613",
+"G c #C24C18",
+"H c #F53A1B",
+"I c #FF7D8C",
+"J c #FF7373",
+"K c #FF5D65",
+"L c #FF4F4B",
+"M c #F04656",
+"N c #F13B4C",
+"O c #F3253D",
+"P c #FE142A",
+"Q c #F80410",
+"R c #FF0F0F",
+"S c #FC0C00",
+"T c #EE1600",
+"U c #FF4633",
+"V c #BF390F",
+"W c #EB100B",
+"X c #FF4351",
+"Y c #FF374F",
+"Z c #FF4350",
+"` c #FF253A",
+" . c #FF2131",
+".. c #F20410",
+"+. c #F30309",
+"@. c #EA0006",
+"#. c #E60000",
+"$. c #E00000",
+"%. c #D8270A",
+"&. c #D2480C",
+"*. c #E20606",
+"=. c #FF5974",
+"-. c #FF4F64",
+";. c #FF334B",
+">. c #FF2736",
+",. c #F7292E",
+"'. c #FF0D0D",
+"). c #EA0600",
+"!. c #F20B00",
+"~. c #E61600",
+"{. c #FF1F01",
+"]. c #DA1F00",
+"^. c #CA2E0A",
+"/. c #B54A29",
+"(. c #BA2C00",
+"_. c #D23100",
+":. c #CA2B00",
+"<. c #CE2C00",
+"[. c #C1561B",
+"}. c #B63108",
+"|. c #CE1800",
+"1. c #E00500",
+"2. c #E00B00",
+"3. c #FF1E13",
+"4. c #AE0004",
+"5. c #DA3408",
+"6. c #A61F00",
+"7. c #F41700",
+"8. c #E60C1C",
+"9. c #D01D00",
+"0. c #D34615",
+"a. c #8E1100",
+"b. c #FF3127",
+"c. c #E02A00",
+"d. c #C1401D",
+"e. c #A61B00",
+"f. c #E42000",
+"g. c #A12205",
+"h. c #BF2B03",
+" . + ",
+" @ # $ ",
+" % & * = ",
+" - ; > , ' ",
+") ! ~ { ] ^ / ( _ : < [ } ",
+"| 1 2 3 4 5 6 7 8 9 0 a b c ",
+"d e f g h i j k l m n o p q r ",
+"s t u v k w x y z A B C D E F G ",
+"H I J K L M N O P Q R S T U m V ",
+"W E X Y Z ` .D + # $ % &. ",
+"*.=.-.;.>.,.'.R ).!.~.{.].^. ",
+"/.(._.:.<.[.}.|.1.2.3.4.5. ",
+" 6.7.8.9.0. ",
+" a.b.c.d. ",
+" e.f.g. ",
+" h.a. "};
diff --git a/pixmaps/file-type-icons/file_type_unknown.xpm b/pixmaps/file-type-icons/file_type_unknown.xpm
new file mode 100644
index 0000000..d43f4cf
--- /dev/null
+++ b/pixmaps/file-type-icons/file_type_unknown.xpm
@@ -0,0 +1,42 @@
+/* XPM */
+static char * file_type_unknown_xpm[] = {
+"16 16 23 1",
+" c None",
+". c #F9F4FB",
+"+ c #E5E8E4",
+"@ c #DBDCDB",
+"# c #D9D9D9",
+"$ c #F9F9F9",
+"% c #CBD1CA",
+"& c #E3E5F0",
+"* c #FAFBFA",
+"= c #F8FCFD",
+"- c #FDFDFD",
+"; c #DADCDF",
+"> c #DEDFEC",
+", c #F4F8F3",
+"' c #F1F2F1",
+") c #DDE4DB",
+"! c #D4DAD2",
+"~ c #EBEEEA",
+"{ c #94C77A",
+"] c #B5D8A4",
+"^ c #71B74F",
+"/ c #369B0D",
+"( c #FFFFFF",
+" *!^///^]~ ",
+" ~^//^^^^//] ",
+" ~^/{)(((,]^/] ",
+",^/](({^{'()^/) ",
+"!/{(~/////)(!/^ ",
+"^/+(^/{!^/{*$^/~",
+"/^(({]=(~/^,.]/!",
+"/^((((((]/{.&]/]",
+"/^((((,{/^,~&{/!",
+"^^'(-(]^^'~ #{/+",
+"]/].'.){]'@@%/^,",
+"'//!~.]/^~;#^/] ",
+" !//]>)]!+%^/{ ",
+" !//^{]{{//{ ",
+" +{/////^] ",
+" (~)])~$ "};
diff --git a/src/Makefile.am b/src/Makefile.am
index b8a5613..2700205 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -49,6 +49,12 @@ gnome_commander_SOURCES = \
gnome-cmd-file-props-dialog.h gnome-cmd-file-props-dialog.cc \
gnome-cmd-file-selector.h gnome-cmd-file-selector.cc \
gnome-cmd-file.h gnome-cmd-file.cc \
+ gnome-cmd-foldview.h gnome-cmd-foldview.cc \
+ gnome-cmd-foldview-control.cc \
+ gnome-cmd-foldview-gvfs.h gnome-cmd-foldview-gvfs.cc \
+ gnome-cmd-foldview-model.cc \
+ gnome-cmd-foldview-private.h \
+ gnome-cmd-foldview-view.cc \
gnome-cmd-hintbox.h gnome-cmd-hintbox.cc \
gnome-cmd-includes.h \
gnome-cmd-key-shortcuts-dialog.h gnome-cmd-key-shortcuts-dialog.cc \
diff --git a/src/gnome-cmd-foldview-control.cc b/src/gnome-cmd-foldview-control.cc
new file mode 100644
index 0000000..0dcc8f5
--- /dev/null
+++ b/src/gnome-cmd-foldview-control.cc
@@ -0,0 +1,905 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ ---------------------------------------------------------------------------
+
+ C++
+
+ Contains variadic macros
+
+ ---------------------------------------------------------------------------
+
+ 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 option) 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <gtk/gtksignal.h>
+#include <gtk/gtkvbox.h>
+
+#include <libgnomevfs/gnome-vfs.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+
+#include "gnome-cmd-includes.h"
+#include "gnome-cmd-combo.h"
+#include "gnome-cmd-main-win.h"
+#include "gnome-cmd-style.h"
+#include "gnome-cmd-data.h"
+#include "gnome-cmd-plain-path.h"
+#include "gnome-cmd-con.h"
+#include "gnome-cmd-con-smb.h"
+#include "gnome-cmd-con-device.h"
+#include "gnome-cmd-con-list.h"
+
+#include "gnome-cmd-foldview-private.h"
+#include "gnome-cmd-foldview-gvfs.h"
+
+// ***************************************************************************
+// * *
+// * Defines *
+// * *
+// ***************************************************************************
+//#define DEBUG_CCIE
+//#define DEBUG_CIE
+
+// ***************************************************************************
+// * *
+// * Helpers *
+// * *
+// ***************************************************************************
+
+// Logging for "Control Check If Empty" functions & callbacks
+#ifdef DEBUG_CCIE
+
+ #define CCIE_INF(...) \
+ { \
+ gwr_gvfs_inf(__VA_ARGS__); \
+ }
+ #define CCIE_WNG(...) \
+ { \
+ gwr_gvfs_wng(__VA_ARGS__); \
+ }
+ #define CCIE_ERR(...) \
+ { \
+ gwr_gvfs_err( __VA_ARGS__); \
+ }
+
+#else
+
+ #define CCIE_INF(...)
+ #define CCIE_WNG(...)
+ #define CCIE_ERR(...)
+
+#endif
+
+// Logging for "Control Iter Expand" functions & callbacks
+#ifdef DEBUG_CIE
+
+ #define CIE_INF(...) \
+ { \
+ gwr_gvfs_inf(__VA_ARGS__); \
+ }
+ #define CCE_WNG(...) \
+ { \
+ gwr_gvfs_wng(__VA_ARGS__); \
+ }
+ #define CIE_ERR(...) \
+ { \
+ gwr_gvfs_err( __VA_ARGS__); \
+ }
+
+#else
+
+ #define CIE_INF(...)
+ #define CIE_WNG(...)
+ #define CIE_ERR(...)
+
+#endif
+
+
+
+
+//=============================================================================
+// Common vars
+//=============================================================================
+GcmdGtkFoldview::View::ctx_menu GcmdGtkFoldview:: s_context_menu =
+{
+ NULL, (gint)2,
+ {
+ {
+ _("Directory"), (gint)3,
+ {
+ //connect title callback
+ {{ TRUE, _("Open in active tab"), G_CALLBACK(GcmdGtkFoldview::Control_set_active_tab) }, NULL, (gulong)0 },
+ {{ TRUE, _("Open in a new tab"), G_CALLBACK(GcmdGtkFoldview::Control_open_new_tab) }, NULL, (gulong)0 },
+ {{ FALSE, _("Set as new root"), G_CALLBACK(GcmdGtkFoldview::Control_set_new_root) }, NULL, (gulong)0 },
+ {{ FALSE, _("nothing"), NULL }, NULL, (gulong)0 },
+ {{ FALSE, _("nothing"), NULL }, NULL, (gulong)0 }
+ }
+ },
+ {
+ _("Treeview"), (gint)2,
+ {
+ //connect title callback
+ {{ FALSE, _("Sync treeview"), G_CALLBACK(GcmdGtkFoldview::Control_sync_treeview) }, NULL, (gulong)0 },
+ {{ FALSE , _("Unsync treeview"), G_CALLBACK(GcmdGtkFoldview::Control_unsync_treeview)}, NULL, (gulong)0 },
+ {{ FALSE, _("nothing"), NULL }, NULL, (gulong)0 },
+ {{ FALSE, _("nothing"), NULL }, NULL, (gulong)0 },
+ {{ FALSE, _("nothing"), NULL }, NULL, (gulong)0 }
+ }
+ }
+ }
+};
+
+//=============================================================================
+// init_instance, ...
+//=============================================================================
+void GcmdGtkFoldview::control_raz_pointers()
+{
+ // sync
+ a_synced_list = NULL;
+ a_synced = FALSE;
+}
+void GcmdGtkFoldview::control_init_instance()
+{
+ gwr_inf("TEST (avoiding gcc warnings at compilation)");
+ gwr_wng("TEST (avoiding gcc warnings at compilation)");
+ gwr_err("TEST (avoiding gcc warnings at compilation)");
+
+ control_raz_pointers();
+
+ model.init_instance();
+ view.init_instance(GTK_WIDGET(this), model.treemodel());
+
+ if ( !GVFS_qstack_initialized() )
+ GVFS_qstack_initialize();
+
+ control_create();
+
+ root_uri_set_1((gchar*)"/");
+}
+gboolean GcmdGtkFoldview::control_create()
+{
+ return TRUE;
+}
+void GcmdGtkFoldview::control_destroy()
+{
+}
+
+//=============================================================================
+// Contextual menu
+//=============================================================================
+void GcmdGtkFoldview::control_context_menu_populate_add_separator(GtkWidget *widget)
+{
+ gtk_menu_shell_append(GTK_MENU_SHELL(widget), gtk_separator_menu_item_new());
+}
+
+void GcmdGtkFoldview::control_context_menu_populate_add_section(
+ GtkWidget *widget,
+ gint i,
+ View::ctx_menu_data *ctxdata)
+{
+ gint j = 0;
+ View::ctx_menu_section *s = &( s_context_menu.a_section[i] );
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ for ( j = 0 ; j != s->a_card ; j++ )
+ {
+ View::ctx_menu_entry *e = &( s->a_entry[j] );
+
+ e->a_widget = gtk_menu_item_new_with_label(e->a_desc.a_text);
+
+ // disconnect current handler
+ // -> no coz these are new widgets at each popup
+
+ if ( ! e->a_desc.a_connect )
+ {
+ gtk_widget_set_sensitive(e->a_widget,FALSE);
+ }
+ else
+ {
+ // connect with new ctx data
+ e->a_handle = g_signal_connect(
+ e->a_widget,
+ "activate",
+ e->a_desc.a_callback,
+ (gpointer)ctxdata);
+ }
+
+ // add to menu
+ gtk_menu_shell_append(GTK_MENU_SHELL(widget), e->a_widget);
+ }
+}
+
+void GcmdGtkFoldview::Control_set_active_tab(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_foldview->control_set_active_tab(ctxdata->d_path_selected);
+ delete ctxdata;
+}
+void GcmdGtkFoldview::control_set_active_tab(GtkTreePath *path)
+{
+ GnomeCmdFileSelector *fs = NULL;
+ GnomeVFSURI *uri = NULL;
+ GtkTreeIter iter = Model::s_iter_NULL;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //gwr_inf("control_open_active_tab");
+
+ fs = main_win->fs(ACTIVE);
+ if ( ! GNOME_CMD_IS_FILE_SELECTOR (fs) )
+ return;
+
+ // get the path from the item selectionned in the treeview
+ if ( !model.iter_from_path(path, &iter) )
+ return;
+
+ uri = model.iter_get_uri_new(&iter);
+ if ( uri == NULL )
+ return;
+
+ control_gcmd_file_list_set_connection(fs->file_list(), uri);
+
+ gnome_vfs_uri_unref(uri);
+}
+
+void GcmdGtkFoldview::Control_open_new_tab(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_foldview->control_open_new_tab(ctxdata->d_path_selected);
+ delete ctxdata;
+}
+void GcmdGtkFoldview::control_open_new_tab(GtkTreePath *path)
+{
+ GnomeVFSURI *uri = NULL;
+ GnomeCmdPath *gnomecmdpath = NULL;
+ GnomeCmdDir *gnomecmddir = NULL;
+ GtkTreeIter iter = Model::s_iter_NULL;
+
+ //gwr_inf("control_open_new_tab");
+
+ if ( !model.iter_from_path(path, &iter) )
+ return;
+
+ uri = model.iter_get_uri_new(&iter);
+
+ if ( uri == NULL )
+ return;
+
+ // open the new tab
+ gnomecmdpath = gnome_cmd_plain_path_new(uri->text);
+ gnomecmddir = gnome_cmd_dir_new(model.connection(), gnomecmdpath);
+ main_win->fs(ACTIVE)->new_tab(gnomecmddir, TRUE);
+
+ // free temp objects
+ gnome_vfs_uri_unref(uri);
+}
+
+void GcmdGtkFoldview::Control_set_new_root(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_foldview->control_set_new_root(ctxdata);
+ delete ctxdata;
+}
+void GcmdGtkFoldview::control_set_new_root(GcmdGtkFoldview::View::ctx_menu_data *ctxdata)
+{
+ GnomeVFSURI *uri = NULL;
+ GtkTreeIter iter = Model::s_iter_NULL;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //gwr_inf("control_set_new_root");
+
+ if ( !model.iter_from_path(ctxdata->d_path_selected, &iter) )
+ return;
+
+ uri = model.iter_get_uri_new(&iter);
+
+ if ( uri == NULL )
+ return;
+
+ // set new root
+ control_root_uri_set(uri);
+
+ // free temp objects
+ gnome_vfs_uri_unref(uri);
+}
+
+GcmdGtkFoldview::eSyncState GcmdGtkFoldview::control_sync_check()
+{
+ if ( !a_synced )
+ {
+ if ( !a_synced_list )
+ {
+ return SYNC_N_LIST_N;
+ }
+ else
+ {
+ return SYNC_N_LIST_Y;
+ }
+ }
+ else
+ {
+ if ( !a_synced_list )
+ {
+ return SYNC_Y_LIST_N;
+ }
+ else
+ {
+ return SYNC_Y_LIST_Y;
+ }
+ }
+}
+
+void GcmdGtkFoldview::Control_sync_update(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_foldview->control_sync_update(ctxdata);
+ delete ctxdata;
+}
+void GcmdGtkFoldview::control_sync_update(GcmdGtkFoldview::View::ctx_menu_data *ctxdata)
+{
+ GnomeVFSURI *uri = NULL;
+ GtkTreeIter iter = Model::s_iter_NULL;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //gwr_inf("control_sync_update");
+
+ if ( control_sync_check() != SYNC_Y_LIST_Y )
+ {
+ //gwr_wng("control_sync_update:not SYNC_Y_LIST_Y:%03i", control_sync_check());
+ return;
+ }
+
+ if ( !model.iter_from_path(ctxdata->d_path_clicked, &iter) )
+ return;
+
+ uri = model.iter_get_uri_new(&iter);
+ if ( uri == NULL )
+ return;
+
+ control_gcmd_file_list_set_connection(a_synced_list, uri);
+}
+
+void GcmdGtkFoldview::Control_unsync_treeview(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_foldview->control_unsync_treeview();
+ delete ctxdata;
+}
+void GcmdGtkFoldview::control_unsync_treeview()
+{
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //gwr_inf("control_unsync_treeview");
+
+ switch ( control_sync_check() )
+ {
+ case SYNC_N_LIST_N:
+ gwr_wng("control_unsync_treeview:not synced");
+ return;
+ break;
+
+ case SYNC_N_LIST_Y:
+ gwr_err("control_unsync_treeview:* mismatch * SYNC_N_LIST_Y");
+ break;
+
+ case SYNC_Y_LIST_Y:
+ a_synced = FALSE;
+ g_object_remove_weak_pointer( G_OBJECT(a_synced_list), (gpointer*)(&a_synced_list) );
+ a_synced_list = NULL;
+ break;
+
+ case SYNC_Y_LIST_N:
+ gwr_inf("control_unsync_treeview:SYNC_Y_LIST_N");
+ a_synced = FALSE;
+ break;
+ }
+}
+
+void GcmdGtkFoldview::Control_sync_treeview(
+ GtkMenuItem *menu_item,
+ View::ctx_menu_data *ctxdata)
+{
+ ctxdata->a_foldview->control_sync_treeview(ctxdata);
+ delete ctxdata;
+}
+void GcmdGtkFoldview::control_sync_treeview(GcmdGtkFoldview::View::ctx_menu_data *ctxdata)
+{
+ GnomeCmdFileList *list = NULL;
+ GnomeVFSURI *uri = NULL;
+ GtkTreeIter iter = Model::s_iter_NULL;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //gwr_inf("control_sync_treeview");
+
+ // We use weak pointers on the GnomeCmdFileList so if the user close
+ // the tab, we can know it coz the weak pointer is set to NULL by glib
+
+ if ( !model.iter_from_path(ctxdata->d_path_selected, &iter) )
+ {
+ gwr_wng("control_sync_treeview:no selected item");
+ return;
+ }
+
+ uri = model.iter_get_uri_new(&iter);
+ if ( uri == NULL )
+ {
+ gwr_wng("control_sync_treeview:iter_get_uri_new failed");
+ return;
+ }
+
+ list = main_win->fs(ACTIVE)->file_list();
+ if ( list == NULL )
+ {
+ gwr_wng("control_sync_treeview:coudnot get file_list");
+ return;
+ }
+
+ switch ( control_sync_check() )
+ {
+ // synchronize with the given list
+ case SYNC_N_LIST_N:
+ a_synced = TRUE;
+ a_synced_list = list;
+
+ g_object_add_weak_pointer( G_OBJECT(list), (gpointer*)(&a_synced_list) );
+
+ control_gcmd_file_list_set_connection(a_synced_list, uri);
+ break;
+
+ // we are synchronized with a file_list that was deleted
+ // simply synchronize with the given list
+ case SYNC_Y_LIST_N:
+ gwr_wng("control_sync_treeview:SYNC_Y_LIST_N");
+
+ a_synced = TRUE;
+ a_synced_list = list;
+
+ g_object_add_weak_pointer( G_OBJECT(list), (gpointer*)(&a_synced_list) );
+
+ control_gcmd_file_list_set_connection(a_synced_list, uri);
+ break;
+
+ case SYNC_Y_LIST_Y:
+ gwr_wng("control_sync_treeview:already synced");
+ break;
+
+ case SYNC_N_LIST_Y:
+ gwr_err("control_unsync_treeview:* mismatch * SYNC_N_LIST_Y");
+ break;
+ }
+
+ // free temp uri
+ gnome_vfs_uri_unref(uri);
+}
+
+
+//=============================================================================
+// control_iter_expand
+//
+// - Find all subdirs
+// - For each subdir : call control_check_if_empty
+//=============================================================================
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Iter expansion static callback MULTITHREAD
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// MULTITHREAD
+
+void GcmdGtkFoldview::control_iter_expand_callback_1(gvfs_async *ga)
+{
+ gvfs_async_load_subdirs *ls = NULL;
+ gvfs_file *file = NULL;
+
+ GcmdGtkFoldview *foldview = NULL;
+
+ gint i = 0;
+ gint count = 0;
+
+ GtkTreeIter *child_iter = NULL;
+
+ GtkTreePath *parent_path_gtk = NULL;
+ GtkTreeIter *parent_iter = NULL;
+
+ gboolean b = FALSE;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ gdk_threads_enter(); // _GDK_LOCK_
+
+ foldview = GcmdFoldview();
+
+ ls = (gvfs_async_load_subdirs*)(ga->ad());
+
+ count = ls->len();
+
+ parent_path_gtk = gtk_tree_path_new_from_string(ls->ppath());
+ parent_iter = Model::Iter_new(NULL);
+ child_iter = Model::Iter_new(NULL);
+ if ( !gtk_tree_model_get_iter(foldview->model.treemodel(), parent_iter, parent_path_gtk) )
+ {
+ CIE_ERR("ciec_1:gtk_tree_model_get_iter failed for parent !");
+ return;
+ }
+ CIE_INF("ciec_1:[0x%16x][0x%16x]", parent_iter, child_iter);
+ // check is name is the same // __GWR__TODO__
+
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // loop 1 : add children
+ for ( i = 0 ; i != count ; i++ )
+ {
+ file = ls->element(i);
+ CIE_INF("ciec_1:%s", file->name());
+
+ // determine icon number for the file element
+ GcmdGtkFoldview::View::eIcon icon = GcmdGtkFoldview::View::eIconUnknown;
+ if ( file->is_dir() )
+ {
+ // Thanks GVFS
+ if ( file->flagged_symlink() )
+ {
+ icon = GcmdGtkFoldview::View::Icon_from_type_access(
+ GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK,
+ file->access());
+ }
+ else
+ {
+ icon = GcmdGtkFoldview::View::Icon_from_type_access(
+ GNOME_VFS_FILE_TYPE_DIRECTORY,
+ file->access());
+ }
+ }
+
+ // add to the model
+ if ( i == 0 )
+ {
+ foldview->model.iter_replace_first_child(parent_iter, child_iter, file->name(), icon);
+ }
+ else
+ {
+ foldview->model.iter_add_child(parent_iter, child_iter, file->name(), icon);
+ }
+
+ // NOTHING here ! Because the sort function mix all - iter or path !!!
+ //child_uri = foldview->model.iter_get_uri_new(child_iter);
+ //foldview->control_check_if_empty(child_iter);
+ //gnome_vfs_uri_unref(child_uri);
+ }
+
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // loop 2 : check if children are empty or not
+ b = gtk_tree_model_iter_children( foldview->model.treemodel(), child_iter, parent_iter);
+ while ( b )
+ {
+ foldview->control_check_if_empty(child_iter);
+ b = gtk_tree_model_iter_next( foldview->model.treemodel(), child_iter);
+ }
+
+ // delete user data
+ delete ga->cd();
+
+ gdk_threads_leave(); // _GDK_LOCK_
+}
+// MULTITHREAD
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Iter expansion private call
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void GcmdGtkFoldview::control_iter_expand_p(
+ GnomeVFSURI *parent_uri,
+ gchar *parent_path)
+{
+ gvfs_async_caller_data *cd = NULL;
+ //control_user_data *ud = NULL;
+
+ //ud = struct_control_user_data::New(this, parent);
+
+ cd = new (control_iter_expand_callback_1, NULL)gvfs_async_caller_data;
+
+ GVFS_async_load_subdirectories(parent_uri, parent_path, cd,-1,TRUE); // _ASYNC_CALL_
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Iter expansion public call
+// - Remove the [DUMMY] item if present ( no dummy doesnt imply no subdirs ;
+// things can change between two users clicks... )
+// - Add the subdirs
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void
+GcmdGtkFoldview::control_iter_expand(
+ GtkTreeIter *parent)
+{
+ GnomeVFSURI *parent_uri;
+ gchar *parent_path;
+ GtkTreePath *temp_path;
+ gint n;
+
+ // Ensure that there is only one subitem ( the [DUMMY] one ( we hope ) )
+ n = model.iter_n_children(parent);
+ if ( n != 1 )
+ {
+ CIE_ERR("ccie :control_iter_expand:parent has %i children", n);
+ return;
+ }
+
+ // new uri that will be destroyed at the end of GVFS callback
+ parent_uri = model.iter_get_uri_new(parent);
+
+ // string representing the GtkTreePath of the parent ; we dont use
+ // a GtkTreePath directly,since it is a GtkObject and maybe invalided
+ // when GVFS callback code will run. Neither use we any GtkTreeIter.
+ temp_path = gtk_tree_model_get_path(model.treemodel(), parent);
+ parent_path = gtk_tree_path_to_string(temp_path);
+ gtk_tree_path_free(temp_path);
+
+ control_iter_expand_p(parent_uri, parent_path);
+}
+
+
+
+//=============================================================================
+// control_check_if_empty static callback
+//
+// - no : add dummy element to the directory ( so the gtktreeview will show
+// an arrow )
+// - yes : nop
+//=============================================================================
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// result callback MULTITHREAD
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// MULTITHREAD
+
+void GcmdGtkFoldview::control_check_if_empty_callback_1(gvfs_async *ga)
+{
+ gvfs_async_load_subdirs *ls = NULL;
+
+ GcmdGtkFoldview *foldview = NULL;
+
+ gint count = 0;
+
+ gchar *str = NULL;
+
+ GtkTreeIter *child_iter = NULL;
+
+ GtkTreePath *parent_path_gtk = NULL;
+ GtkTreeIter *parent_iter = NULL;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ gdk_threads_enter(); // _GDK_LOCK_
+
+ foldview = GcmdFoldview();
+
+ ls = (gvfs_async_load_subdirs*)(ga->ad());
+
+ count = ls->len();
+
+ // Since we are on an async call, GtkTreePath may points to something else // __GWR__WARNING__
+ // Ex : filesystem notification, user click...
+ // This is a BIG problem. Maybe queue requests ?
+ parent_path_gtk = gtk_tree_path_new_from_string(ls->ppath());
+ parent_iter = Model::Iter_new(NULL);
+ child_iter = Model::Iter_new(NULL);
+ if ( !gtk_tree_model_get_iter(foldview->model.treemodel(), parent_iter, parent_path_gtk) )
+ {
+ CCIE_ERR("cciec_1:gtk_tree_model_get_iter failed for parent !");
+ return;
+ }
+ // check is name is the same // __GWR__TODO__
+ CCIE_INF("cciec_1:[0x%16x][0x%16x]", parent_iter, child_iter);
+ if ( count > 0 )
+ {
+ foldview->model.iter_add_child(parent_iter, child_iter, "... Working ...", GcmdGtkFoldview::eAccessReadWrite);
+
+ str = foldview->model.iter_get_string_new(parent_iter);
+ CCIE_INF("cciec_1:adding dummy to parent:[0x%16x]-[0x%16x]-[0x%16x][0x%16x][0x%16x] %s | %s",
+ parent_iter, parent_iter->stamp, parent_iter->user_data, parent_iter->user_data2, parent_iter->user_data3,
+ str, ls->ppath());
+ g_free(str);
+ }
+ else
+ {
+ str = foldview->model.iter_get_string_new(parent_iter);
+ CCIE_INF("cciec_1:adding nothing to parent:[0x%16x]-[0x%16x]-[0x%16x][0x%16x][0x%16x] %s | %s",
+ parent_iter, parent_iter->stamp, parent_iter->user_data, parent_iter->user_data2, parent_iter->user_data3,
+ str, ls->ppath());
+ }
+
+ // delete user data
+ delete ga->cd();
+
+ gdk_threads_leave();
+
+}
+// MULTITHREAD
+
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// control_check_if_empty private call
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void GcmdGtkFoldview::control_check_if_empty_p(GnomeVFSURI *parent_uri, gchar *parent_path)
+{
+ //struct_control_user_data *ud = NULL;
+ gvfs_async_caller_data *cd = NULL;
+
+ //ud = struct_control_user_data::New(this, parent);
+
+ cd = new(control_check_if_empty_callback_1, (gpointer)NULL) gvfs_async_caller_data;
+
+ GVFS_async_load_subdirectories(parent_uri, parent_path, cd, 1,TRUE); // _ASYNC_CALL_
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// control_check_if_empty public call
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void GcmdGtkFoldview::control_check_if_empty(GtkTreeIter *parent)
+{
+ GnomeVFSURI *parent_uri;
+ gchar *parent_path;
+ GtkTreePath *temp_path;
+
+ // new uri that will be destroyed at the end of GVFS callback
+ parent_uri = model.iter_get_uri_new(parent);
+
+ // string representing the GtkTreePath of the parent ; we dont use
+ // a GtkTreePath directly,since it is a GtkObject and maybe invalided
+ // when GVFS callback code will run. Neither use we any GtkTreeIter.
+ temp_path = gtk_tree_model_get_path(model.treemodel(), parent);
+ parent_path = gtk_tree_path_to_string(temp_path);
+
+ gchar *str = gtk_tree_path_to_string( temp_path );
+ CCIE_INF("ccie :control_check_if_empty:parent %s", str);
+ g_free(str);
+
+
+ gtk_tree_path_free(temp_path);
+
+ control_check_if_empty_p(parent_uri, parent_path);
+}
+
+//============================================================================= // _GWR_TODO_ see FAM stuff
+// Item collapsed
+// - Remove all subdirs
+// - Add [DUMMY] ( we have been callapsed, so there were subdirs in there )
+// This is useful, because when re-expanding, directory will be re-scanned
+// and thus we'll be more accurate
+//=============================================================================
+void
+GcmdGtkFoldview::control_iter_collapsed(
+GtkTreeIter *parent)
+{
+ gint removed = 0;
+
+ GtkTreeIter child;
+
+ removed = model.iter_remove_children(parent);
+
+ //gwr_inf("control_iter_collapsed:removed %03i children", removed);
+
+ // we have been collapsed, so we have children ; so re-add dummy child
+ model.iter_add_child(parent, &child, "...Working...", View::eIconUnknown);
+}
+//=============================================================================
+// Divers
+//=============================================================================
+gboolean GcmdGtkFoldview::control_root_uri_set(GnomeVFSURI *uri)
+{
+ GtkTreeIter *parent = NULL;
+
+ model.iter_remove_all();
+
+ model.root.unset();
+
+ if ( !model.root.set(uri) )
+ {
+ ERR_RET(FALSE,"control_root_uri_set:failed");
+ }
+
+ View::eIcon icon = View::Icon_from_type_permissions(
+ GNOME_VFS_FILE_TYPE_DIRECTORY,
+ model.root.m_info->permissions);
+
+ model.iter_add_child(parent, &model.root.m_iter, uri->text, icon);
+ control_check_if_empty(&model.root.m_iter);
+
+ return TRUE;
+}
+
+void GcmdGtkFoldview::control_gcmd_file_list_set_connection(
+ GnomeCmdFileList *list,
+ GnomeVFSURI *uri)
+{
+ GnomeCmdDir *gnomecmddir = NULL;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ //gwr_inf("---------- control_gcmd_file_list_set_connection ----------");
+
+ // connection is open
+ if (model.connection()->state == CON_STATE_OPEN)
+ {
+ gnomecmddir = gnome_cmd_dir_new( model.connection(), gnome_cmd_con_create_path(model.connection(), uri->text) );
+
+ //gnome_cmd_dir_log("control_gcmd_file_list_set_connection 1", gnomecmddir);
+
+ // Avoid gcmd to call gtk_object_destroy on access-denied directories // __GWR_TODO__
+ // and lost+found in GnomeCmdFileList::on_dir_list_failed(...)
+ //
+ // The problem is that gcmd cant handle correctly such directories
+ // when calling GnomeCmdFileList::set_connection,set_directory,
+ // goto_directory, ...I think you get the same result if you bookmark
+ // (manually) such a directory
+ //
+ // Since gcmd increase GnomeCmdFile->ref_cnt until infinite (!),
+ // I feel allowed to call gnome_cmd_dir_ref rather than
+ // g_object_ref_sink :)
+ //g_object_ref_sink(gnomecmddir);
+ gnome_cmd_dir_ref(gnomecmddir);
+
+ //gnome_cmd_dir_log("control_gcmd_file_list_set_connection 2", gnomecmddir);
+
+ // call set_connection instead of set_/goto_ directory because
+ // foldview has its own connection combo
+ list->set_connection(model.connection(), gnomecmddir);
+ }
+ // connection is closed
+ else
+ {
+ // if base_path, delete it
+ if ( model.connection()->base_path )
+ g_object_unref (model.connection()->base_path);
+
+ // set connection base_path
+ model.connection()->base_path = gnome_cmd_con_create_path(model.connection(), uri->text);
+ g_object_ref(G_OBJECT(model.connection()->base_path));
+
+ // go
+ list->set_connection(model.connection(), NULL);
+ }
+}
+
+
+void GcmdGtkFoldview::control_connection_combo_update()
+{
+ gboolean found_my_con = FALSE;
+ GnomeCmdCombo *combo = GNOME_CMD_COMBO(view.connection_combo());
+
+ view.connection_combo_reset();
+
+ for (GList *l=gnome_cmd_con_list_get_all (gnome_cmd_con_list_get ()); l; l = l->next)
+ {
+ GnomeCmdCon *con = (GnomeCmdCon *)l->data;
+
+ // dont add connection if
+ // it is closed AND it is not a device AND it is not smb
+ if (
+ !gnome_cmd_con_is_open (con) &&
+ !GNOME_CMD_IS_CON_DEVICE (con) &&
+ !GNOME_CMD_IS_CON_SMB (con)
+ ) continue;
+
+ // else add it
+ view.connection_combo_add_connection(con);
+
+ if ( con == model.connection())
+ found_my_con = TRUE;
+ }
+
+ // If the connection is no longer available use the home connection
+ if ( !found_my_con )
+ model.connection(get_home_con());
+ else
+ combo->select_data(model.connection());
+}
diff --git a/src/gnome-cmd-foldview-gvfs.cc b/src/gnome-cmd-foldview-gvfs.cc
new file mode 100644
index 0000000..3eaa0c1
--- /dev/null
+++ b/src/gnome-cmd-foldview-gvfs.cc
@@ -0,0 +1,731 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ ---------------------------------------------------------------------------
+
+ C++
+
+ Contains variadic macros
+
+ ---------------------------------------------------------------------------
+
+ 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 option) 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <gtk/gtksignal.h>
+#include <gtk/gtkvbox.h>
+
+#include <libgnomevfs/gnome-vfs.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+
+#include "gnome-cmd-includes.h"
+#include "gnome-cmd-combo.h"
+#include "gnome-cmd-main-win.h"
+#include "gnome-cmd-style.h"
+#include "gnome-cmd-data.h"
+
+#include "gnome-cmd-foldview-private.h"
+#include "gnome-cmd-foldview-gvfs.h"
+
+// ***************************************************************************
+// * *
+// * Defines *
+// * *
+// ***************************************************************************
+#define GVFS_ITEMS_PER_NOTIFICATION 30
+
+#define DEBUG_GVFS_ALSC
+
+// ***************************************************************************
+// * *
+// * Helpers *
+// * *
+// ***************************************************************************
+static char sLogStr [1024];
+
+void gwr_gvfs_inf(const char* fmt, ...)
+{
+ #ifndef DEBUG_SHOW_GVFS_INF
+ return;
+ #endif
+ va_list val; va_start(val, fmt); vsprintf(sLogStr, fmt, val); va_end(val);
+ gwr_inf("GVFS:%s", sLogStr);
+}
+void gwr_gvfs_wng(const char* fmt, ...)
+{
+ #ifndef DEBUG_SHOW_GVFS_WNG
+ return;
+ #endif
+ va_list val; va_start(val, fmt); vsprintf(sLogStr, fmt, val); va_end(val);
+ gwr_wng("GVFS:%s", sLogStr);
+}
+void gwr_gvfs_err(const char* fmt, ...)
+{
+ #ifndef DEBUG_SHOW_GVFS_ERR
+ return;
+ #endif
+ va_list val; va_start(val, fmt); vsprintf(sLogStr, fmt, val); va_end(val);
+ gwr_err("GVFS:%s", sLogStr);
+}
+
+//=============================================================================
+#ifdef DEBUG_GVFS_ALSC
+
+ #define ALSC_INF(...) \
+ { \
+ gwr_gvfs_inf(__VA_ARGS__); \
+ }
+ #define ALSC_WNG(...) \
+ { \
+ gwr_gvfs_wng(__VA_ARGS__); \
+ }
+ #define ALSC_ERR(...) \
+ { \
+ gwr_gvfs_err( __VA_ARGS__); \
+ }
+
+#else
+
+ #define ALSC_INF(...)
+ #define ALSC_WNG(...)
+ #define ALSC_ERR(...)
+
+#endif
+
+
+
+//=============================================================================
+// Common vars
+//=============================================================================
+static GnomeVFSResult sVFSResult = GNOME_VFS_OK; // for sync operations
+
+
+// ***************************************************************************
+// * *
+// * Gnome VFS - Misc *
+// * *
+// ***************************************************************************
+
+gboolean // __GWR__TODO__ inline
+GVFS_vfsinfo_has_type_directory(
+ GnomeVFSFileInfo *info)
+{
+ if ( !(info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) )
+ return FALSE;
+
+ return ( (info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) ? TRUE : FALSE );
+}
+gboolean // __GWR__TODO__ inline
+GVFS_vfsinfo_has_type_symlink(
+ GnomeVFSFileInfo *info)
+{
+ if ( !(info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE) )
+ return FALSE;
+
+ return ( (info->type == GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK) ? TRUE : FALSE );
+}
+
+gboolean
+GVFS_vfsinfo_is_true_directory(
+ GnomeVFSFileInfo *info)
+{
+ // This is memory-access broken but Im fed up with utf8 _GWR_TODO_
+
+ if (
+ ( info->name[0] == '.' ) &&
+ ( info->name[1] == 0 )
+ )
+ return FALSE;
+
+ if (
+ ( info->name[0] == '.' ) &&
+ ( info->name[1] == '.' ) &&
+ ( info->name[2] == 0 )
+ )
+ return FALSE;
+
+ return TRUE;
+}
+
+
+GnomeVFSURI*
+GVFS_uri_new(const gchar *text)
+{
+ // well-formed_text
+ gchar *temp = gnome_vfs_make_uri_from_input(text);
+ // new uri
+ GnomeVFSURI *uri = gnome_vfs_uri_new(temp);
+ g_free(temp);
+
+ return uri;
+}
+
+
+// ***************************************************************************
+// * *
+// * Gnome VFS - Sync ops *
+// * *
+// ***************************************************************************
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Test if an uri exists
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gboolean GVFS_info_from_uri(GnomeVFSURI* uri, GnomeVFSFileInfo* info)
+{
+ sVFSResult = gnome_vfs_get_file_info_uri(uri, info,
+ (GnomeVFSFileInfoOptions)(GNOME_VFS_FILE_INFO_DEFAULT |
+ GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS));
+
+ ERR_VFS_RET(FALSE, "vfs_sync_uri_is_directory: couldnt get info for uri");
+
+ return TRUE;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Test is a directory contains subdirectories
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+/*
+static gboolean gvfs_dir_has_subdirs(GnomeVFSURI *uri)
+{
+ GList *list;
+ GList *l;
+ GnomeVFSFileInfo *info;
+ gboolean bRes;
+
+ sVFSResult = gnome_vfs_directory_list_load(
+ &list,
+ uri->text,
+ GNOME_VFS_FILE_INFO_DEFAULT);
+
+ ERR_VFS_RET(FALSE, "vfs_sync_dir_has_subdirs:gnome_vfs_directory_list_load failed");
+
+ bRes = FALSE;
+ l = g_list_first(list);
+ while ( l != NULL )
+ {
+ info = (GnomeVFSFileInfo*)(l->data);
+
+ if (
+ GVFS_vfsinfo_has_type_directory(info) &&
+ GVFS_vfsinfo_is_true_directory(info)
+ )
+ {
+ //warn_print("subfolder:%s\n", info->name);
+ bRes = TRUE;
+ break;
+ }
+
+ l = g_list_next(l);
+ }
+
+ g_list_free(list);
+ return bRes;;
+}
+*/
+// ***************************************************************************
+// * *
+// * Gnome VFS - Async ops *
+// * *
+// ***************************************************************************
+//static GStaticMutex GVFS_qstack_Mutex = G_STATIC_MUTEX_INIT; __GWR__TODO__
+
+//=============================================================================
+// Handles for vfs async ops
+//
+// Handle creation : from user action only -> monothread
+// Handle release : from gvfs callbacks, but always on different handles
+// -> monothread ; the only risk is to return "no more handle ptr available"
+// when a gvfs callback just freed one.
+//=============================================================================
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// QuickStack
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static gboolean GVFS_qstack_init = FALSE;
+
+static guint32 GVFS_qstack_el_core_size = sizeof(GnomeVFSAsyncHandle*);
+static guint32 GVFS_qstack_ix_core_size = sizeof(guint32);
+
+static guint32 GVFS_qstack_step = 10;
+static guint32 GVFS_qstack_size = 0;
+
+static GnomeVFSAsyncHandle** GVFS_qstack_el = NULL;
+static guint32* GVFS_qstack_ix = NULL;
+static guint32 GVFS_qstack_ff = 0;
+
+gboolean GVFS_qstack_initialized()
+{
+ return GVFS_qstack_init;
+}
+
+void GVFS_qstack_initialize()
+{
+ guint32 i = 0;
+
+ // alloc for pointers
+ if ( GVFS_qstack_el )
+ {
+ gwr_err("GVFS_qstack_init:GVFS_qstack_el is not NULL - already initialized ?");
+ return;
+ }
+ GVFS_qstack_el = (GnomeVFSAsyncHandle**)(g_malloc0(GVFS_qstack_el_core_size * GVFS_qstack_step));
+ if ( !GVFS_qstack_el )
+ {
+ gwr_err("GVFS_qstack_init:g_malloc0 failed for GVFS_qstack_el");
+ return;
+ }
+
+ // alloc for indexes
+ if ( GVFS_qstack_ix )
+ {
+ gwr_err("GVFS_qstack_init:GVFS_qstack_ix is not NULL - already initialized ?");
+ return;
+ }
+ GVFS_qstack_ix = (guint32*)(g_malloc0(GVFS_qstack_ix_core_size * GVFS_qstack_step));
+ if ( !GVFS_qstack_ix )
+ {
+ gwr_err("GVFS_qstack_init:g_malloc0 failed for GVFS_qstack_ix");
+ return;
+ }
+
+ // init indexes stack
+ for ( i = 0 ; i != GVFS_qstack_step ; i++ )
+ {
+ GVFS_qstack_ix[i] = GVFS_qstack_step - i - 1;
+ }
+ GVFS_qstack_ff = GVFS_qstack_step - 1;
+
+ // size
+ GVFS_qstack_size = GVFS_qstack_step;
+}
+
+gboolean GVFS_qstack_realloc()
+{
+ gpointer temp = NULL;
+ guint32 i = 0;
+
+ //gwr_wng("GVFS_qstack_realloc at size:%04i", GVFS_qstack_size);
+
+ //.........................................................................
+ // realloc free indexes stack ; since there is no more index free,
+ // we could just realloc - but there is no g_realloc0 in Glib
+
+ // free the old indexes stack
+ g_free(GVFS_qstack_ix);
+
+ // alloc a new stack
+ GVFS_qstack_ix = (guint32*)(g_malloc0(GVFS_qstack_ix_core_size * ( GVFS_qstack_size + GVFS_qstack_step ) ));
+ if ( !GVFS_qstack_ix )
+ {
+ gwr_err("GVFS_qstack_realloc:g_malloc0 failed for GVFS_qstack_ix");
+ return FALSE;
+ }
+
+ // store new free indexes
+ for ( i = 0 ; i != GVFS_qstack_step ; i++ )
+ {
+ GVFS_qstack_ix[i] = GVFS_qstack_size + GVFS_qstack_step - i - 1;
+ }
+
+ //.........................................................................
+ // realloc pointers array
+ temp = (gpointer)GVFS_qstack_el;
+ GVFS_qstack_el = (GnomeVFSAsyncHandle**)(g_malloc0(GVFS_qstack_el_core_size * ( GVFS_qstack_size + GVFS_qstack_step ) ));
+ if ( !GVFS_qstack_el )
+ {
+ gwr_err("GVFS_qstack_realloc:g_malloc0 failed for GVFS_qstack_el");
+ return FALSE;
+ }
+
+ // copy used pointers
+ memcpy( GVFS_qstack_el, temp, GVFS_qstack_el_core_size * GVFS_qstack_size);
+
+ // update stack size
+ GVFS_qstack_size += GVFS_qstack_step;
+
+ // update first free index
+ GVFS_qstack_ff = GVFS_qstack_step - 1;
+
+ return TRUE;
+}
+
+
+guint32 GVFS_qstack_pop()
+{
+ if ( GVFS_qstack_ff == 0 )
+ {
+ //guint32 temp = GVFS_qstack_ff;
+ // index on indexes is zero ; we are missing storage places
+ // -> realloc
+ guint32 index = GVFS_qstack_ix[0];
+ GVFS_qstack_realloc();
+
+ //gwr_inf("GVFS_qstack_pop (realloc):index:%04i ff:%04i->%04i of %04i", index, temp, GVFS_qstack_ff, GVFS_qstack_size-1);
+ return index;
+ }
+
+ //gwr_inf("GVFS_qstack_pop:ff:%04i->%04i of %04i", GVFS_qstack_ff, GVFS_qstack_ff-1, GVFS_qstack_size-1);
+ return GVFS_qstack_ix[GVFS_qstack_ff--];
+}
+void GVFS_qstack_push(guint32 index)
+{
+
+ if ( GVFS_qstack_ff >= GVFS_qstack_size )
+ {
+ gwr_err("GVFS_qstack_push:GVFS_qstack_ff too high");
+ return;
+ }
+
+ //gwr_inf("GVFS_qstack_push:index:%04i ff:%04i->%04i of %04i", index, GVFS_qstack_ff, GVFS_qstack_ff+1, GVFS_qstack_size-1);
+ GVFS_qstack_ix[++GVFS_qstack_ff] = index;
+}
+
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// User calls
+//
+// Maybe should I modify this to GVFS_qstack_get(GVFS_qstack_pop()) __GWR__TODO__
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static guint32 GVFS_async_handle_hold()
+{
+ return GVFS_qstack_pop();
+}
+static void GVFS_async_handle_release(guint32 index)
+{
+ GVFS_qstack_push(index);
+}
+
+static GnomeVFSAsyncHandle *GVFS_async_handle_get(guint32 index)
+{
+ return GVFS_qstack_el[index];
+}
+static GnomeVFSAsyncHandle **GVFS_async_handle_ptr_get(gint32 index)
+{
+ return &( GVFS_qstack_el[index] );
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Cancel an async op
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static void GVFS_async_cancel(gint32 handle_index)
+{
+ gnome_vfs_async_cancel( GVFS_async_handle_get( handle_index ) );
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Cancel all async ops
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void GVFS_async_cancel_all()
+{
+ for ( guint32 i = GVFS_qstack_ff ; i != GVFS_qstack_size ; i++ )
+ {
+ gnome_vfs_async_cancel( GVFS_async_handle_get( i ) );
+ }
+
+ GVFS_qstack_ff = GVFS_qstack_size - 1;
+}
+
+//=============================================================================
+// Base structs for vfs async ops
+//=============================================================================
+
+//.............................................................................
+// gvfs_async_load_subdirs new / del
+//.............................................................................
+void* gvfs_async_load_subdirs::operator new(size_t size, GnomeVFSURI* parent_uri, gchar *parent_path)
+{
+ gvfs_async_load_subdirs *ls = g_try_new0(gvfs_async_load_subdirs, 1);
+
+ if ( !ls )
+ {
+ gwr_err("gvfs_async_load_subdirs::new:g_try_new0 failed");
+ return ls;
+ }
+
+ ls->puri() = parent_uri; // __GWR__TODO__ check ref_count
+ ls->ppath() = parent_path;
+
+ //GArray* g_array_sized_new(
+ //gboolean zero_terminated, zero supplementary element
+ //gboolean clear_, new element to 0
+ //guint element_size,
+ //guint reserved_size); growness
+ ls->array() = g_array_sized_new(
+ FALSE,
+ TRUE,
+ sizeof(gvfs_file*),
+ 10);
+ ls->len() = 0;
+
+ return ls;
+}
+
+void gvfs_async_load_subdirs ::operator delete (void *p)
+{
+ gvfs_file *file = NULL;
+ gvfs_async_load_subdirs *ls = (gvfs_async_load_subdirs*)p;
+
+ // parent uri & path
+ gnome_vfs_uri_unref(ls->puri());
+ g_free(ls->ppath());
+
+ // array elements
+ for ( int i = 0 ; i < ls->len() ; i++ )
+ {
+ file = g_array_index( ls->array(), gvfs_file*, i);
+ delete file;
+ }
+
+ // array
+ g_array_free(ls->array(), TRUE);
+
+ // struct
+ g_free(ls);
+}
+
+//-----------------------------------------------------------------------------
+// Callbacks MULTITHREAD
+//-----------------------------------------------------------------------------
+
+//.............................................................................
+// Add entries...goto is the best
+//.............................................................................
+static void
+GVFS_async_load_subdirectories_callback(
+ GnomeVFSAsyncHandle *handle,
+ GnomeVFSResult result,
+ GList *list,
+ guint entries_read,
+ gpointer data)
+{
+ GnomeVFSFileInfo *info = NULL;
+
+ GList *l = NULL;
+ guint count = 0;
+ guint added = 0;
+
+ gboolean symlink = FALSE;
+
+ gvfs_async *ga = NULL;
+ gvfs_async_load_subdirs *ls = NULL;
+ gvfs_dir *dir = NULL;
+ gvfs_symlink *lnk = NULL;
+ //.........................................................................
+
+ ga = (gvfs_async*) (data);
+ ls = (gvfs_async_load_subdirs*) (ga->ad());
+
+ ALSC_INF("alsc:[%03i] entries:%03i list:%16x parent:[%s]%s", ga->hi(), entries_read, list, ls->ppath(), ls->puri()->text);
+
+ // counter
+ count = 0;
+
+ // handle the '0-entry-case'
+ if ( entries_read == 0 )
+ {
+ goto lab_no_more_entry;
+ }
+
+ // init loop - we have at least one entry
+ l = g_list_first(list);
+
+lab_loop:
+
+ count++;
+
+ info = (GnomeVFSFileInfo*)(l->data);
+ symlink = FALSE;
+
+ //ALSC_INF("alsc:[%03i] entry name:%s", ga->hi(), info->name);
+
+ switch ( info->type )
+ {
+
+ //.....................................................................
+ case GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK:
+
+ // if follow_links is TRUE, we should not be here - except if we have
+ // a broken link. We thus cant know if the link was pointing on a
+ // directory or something else. So ignore it.
+ if ( ls->follow_links() )
+ {
+ ALSC_WNG("alsc:[%03i][0x%16x] [%03i][%03i][%03i] [broken link, ignored]<%s>", ga->hi(), l, count, added, ga->mr(), info->name);
+ break;
+ }
+
+ added++;
+
+ ALSC_INF("alsc:[%03i][0x%16x] [%03i][%03i][%03i] S<%s>", ga->hi(), l, count, added, ga->mr(), info->name);
+
+ lnk = new(g_strdup(info->name), info->permissions, info->flags ) gvfs_symlink;
+ ls->append( (gvfs_file*)lnk );
+
+ // if the caller want partial listing
+ if (
+ ( ga->mr() >= 0 ) &&
+ ( ls->len() >= ga->mr() )
+ )
+ goto lab_abort;
+
+ break;
+
+ //.....................................................................
+ case GNOME_VFS_FILE_TYPE_DIRECTORY :
+
+ if ( GVFS_vfsinfo_is_true_directory(info) )
+ {
+ added++;
+
+ ALSC_INF("alsc:[%03i][0x%16x] [%03i][%03i][%03i] +<%s>", ga->hi(), l, count, added, ga->mr(), info->name);
+
+ dir = new(g_strdup(info->name), info->permissions, info->flags ) gvfs_dir;
+ ls->append( (gvfs_file*)dir );
+
+ // if the caller want partial listing
+ if (
+ ( ga->mr() >= 0 ) &&
+ ( ls->len() >= ga->mr() )
+ )
+ goto lab_abort;
+ }
+ break;
+
+ //.....................................................................
+ default:
+ ALSC_INF("alsc:[%03i][0x%16x] [%03i][%03i][%03i] <%s>", ga->hi(), l, count, added, ga->mr(), info->name);
+ }
+
+ // if gvfs bugs on entries_read, we bug too with this
+ if ( count == entries_read )
+ goto lab_no_more_entry;
+
+ l = g_list_next(l);
+
+ goto lab_loop;
+
+//.............................................................................
+lab_no_more_entry:
+
+ // if OK, simply return, we will be re-called for further entries
+ if ( result == GNOME_VFS_OK )
+ {
+ ALSC_INF("alsc:[%03i][0x%16x] (GNOME_VFS_OK)", ga->hi(), l);
+ return;
+ }
+
+ // else ensure GNOME_VFS_ERROR_EOF is set
+ if ( result == GNOME_VFS_ERROR_EOF )
+ goto lab_eof;
+
+ // else an error as occured : result is not OK, neither EOF.
+ // this occurs for example with symlinks, or access-denied directories ;
+ // show a little warning, and do as EOF, since there is no more entry.
+ ALSC_INF("alsc:[%03i][0x%16x] (NO ENTRY - Jumping to EOF):%s",
+ ga->hi(), l, gnome_vfs_result_to_string(result));
+
+//.............................................................................
+lab_eof:
+
+ ALSC_INF("alsc:[%03i][0x%16x] (EOF)", ga->hi(), l);
+ // Call caller callback ; caller is responsible for freeing memory
+ // eventually allocated in m_user_data member
+ // of the struct_gvfs_caller_data
+ ga->cd()->a_callback( ga );
+
+ // release the handle
+ GVFS_async_handle_release(ga->hi());
+
+ // delete the list
+ delete ls;
+ delete ga;
+
+ // "Final end"
+ return;
+
+//.............................................................................
+lab_abort:
+
+ ALSC_INF("alsc:[%03i][0x%16x] (ABORT)", ga->hi(), l);
+ // Call caller callback ; caller is responsible for freeing memory
+ // eventually allocated in m_user_data member
+ // of the struct_gvfs_caller_data
+ ga->cd()->a_callback( ga );
+
+ // cancel async op
+ GVFS_async_cancel( ga->hi() );
+
+ // release the handle
+ GVFS_async_handle_release(ga->hi());
+
+ // delete the lists
+ delete ls;
+ delete ga;
+
+ // "Final end"
+ //return;
+}
+
+//-----------------------------------------------------------------------------
+// Main call
+//-----------------------------------------------------------------------------
+void GVFS_async_load_subdirectories(
+ GnomeVFSURI *parent_uri,
+ gchar *parent_path,
+ gvfs_async_caller_data *cd,
+ gint max_result,
+ gboolean follow_links)
+{
+ gint32 hi = 0;
+ gvfs_async *ga = NULL;
+ gvfs_async_load_subdirs *ls = NULL;
+
+ // Obtain a handle
+ hi = GVFS_async_handle_hold();
+
+ // Create struct_gvfs_async
+ ga = new (hi,max_result,cd) gvfs_async;
+
+ ls = new(parent_uri, parent_path)gvfs_async_load_subdirs;
+ ls->follow_links() = follow_links;
+
+ ga->ad() = ls;
+
+ gwr_gvfs_inf("als :[%03i] [0x%16x][0x%16x][%03i] Launch", hi, ga, ls, max_result);
+
+ // Launch gvfs async op !
+ // uri ref_count is not incremented
+ gnome_vfs_async_load_directory_uri(
+ GVFS_async_handle_ptr_get(hi),
+ parent_uri,
+ (GnomeVFSFileInfoOptions)
+ (
+ GNOME_VFS_FILE_INFO_DEFAULT |
+ GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS |
+ ( follow_links ? GNOME_VFS_FILE_INFO_FOLLOW_LINKS : 0 )
+ ),
+ GVFS_ITEMS_PER_NOTIFICATION,
+ //GNOME_VFS_PRIORITY_DEFAULT,
+ GNOME_VFS_PRIORITY_MIN,
+ GVFS_async_load_subdirectories_callback,
+ (gpointer)ga);
+}
diff --git a/src/gnome-cmd-foldview-gvfs.h b/src/gnome-cmd-foldview-gvfs.h
new file mode 100644
index 0000000..240f1ea
--- /dev/null
+++ b/src/gnome-cmd-foldview-gvfs.h
@@ -0,0 +1,335 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ 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 option) 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GCMDGTKFOLDVIEW_GVFS_H__
+#define __GCMDGTKFOLDVIEW_GVFS_H__
+
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtklabel.h>
+
+
+//*****************************************************************************
+// Helpers
+//*****************************************************************************
+// Because debugging GVFS generates many logs, we define apart log functions
+//#define DEBUG_SHOW_GVFS_INF
+#define DEBUG_SHOW_GVFS_WNG
+#define DEBUG_SHOW_GVFS_ERR
+
+void gwr_gvfs_inf(const char* fmt, ...);
+void gwr_gvfs_wng(const char* fmt, ...);
+void gwr_gvfs_err(const char* fmt, ...);
+
+//*****************************************************************************
+// Structs
+//*****************************************************************************
+
+/*
+
+ caller function
+ |
+ v
+ launch GVFS op
+ |
+ +------------ gvfs_async
+ |
+ +------------ handle_index, ...
+ |
+ +------------ gvfs_async_caller_data
+ | |
+ | +-------------- gvfs_async_user_callback
+ | |
+ | +-------------- user_data
+ |
+ +-------------------------------------- gvfs_async_load_subdirs
+
+*/
+
+
+//=============================================================================
+// File structs
+//=============================================================================
+struct gvfs_file
+{
+ private:
+ gchar* d_name;
+ GnomeVFSResult a_vfsresult;
+ GnomeVFSFileType a_vfstype;
+ GnomeVFSFileFlags a_vfsflags;
+ GcmdGtkFoldview::eFileAccess a_access;
+ public:
+ gchar*& name() { return d_name; }
+ GcmdGtkFoldview::eFileAccess& access() { return a_access; }
+
+ gboolean flagged_symlink() { return ( (a_vfsflags & GNOME_VFS_FILE_FLAGS_SYMLINK) != 0 ); }
+ gboolean is_symlink() { return ( a_vfstype == GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK ); }
+ gboolean is_dir() { return ( a_vfstype == GNOME_VFS_FILE_TYPE_DIRECTORY ); }
+
+
+ protected:
+ void up(gchar *name, GnomeVFSResult result, GnomeVFSFilePermissions permissions, GnomeVFSFileType type, GnomeVFSFileFlags flags)
+ {
+ d_name = name;
+
+ a_vfsresult = result;
+ a_vfstype = type;
+ a_vfsflags = flags;
+
+ a_access = GcmdGtkFoldview::Access_from_permissions(permissions);
+ }
+ void down()
+ {
+ g_free(d_name);
+ }
+};
+
+struct gvfs_dir : gvfs_file
+{
+ private:
+ void up(gchar *name, GnomeVFSFilePermissions permissions, GnomeVFSFileFlags flags)
+ {
+ gvfs_file::up(name, GNOME_VFS_OK, permissions, GNOME_VFS_FILE_TYPE_DIRECTORY, flags);
+
+ //content() = GcmdGtkFoldview::eContentInit;
+
+ }
+ void down()
+ {
+ gvfs_file::down();
+ }
+
+ public:
+ void* operator new (size_t size, gchar *name, GnomeVFSFilePermissions permissions, GnomeVFSFileFlags flags)
+ {
+ gvfs_dir *dir = g_try_new0(gvfs_dir, 1);
+
+ dir->up(name, permissions, flags);
+
+ return (gvfs_file*)dir;
+ }
+ void operator delete (void *p)
+ {
+ ((gvfs_dir*)p)->down();
+ g_free (p);
+ }
+};
+
+struct gvfs_symlink : gvfs_file
+{
+ private:
+ GArray *d_array;
+ guint a_array_card;
+
+ public:
+ void append(gvfs_symlink* link)
+ {
+
+ }
+ private:
+ gvfs_file *d_target;
+ public:
+ gvfs_file*& target() { return d_target; }
+
+ private:
+ void up(gchar *name, GnomeVFSFilePermissions permissions, GnomeVFSFileFlags flags)
+ {
+ gvfs_file::up(name, GNOME_VFS_OK, permissions, GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK, flags);
+ }
+ void down()
+ {
+ gvfs_file::down();
+ }
+
+ public:
+ void* operator new (size_t size, gchar *name, GnomeVFSFilePermissions permissions, GnomeVFSFileFlags flags)
+ {
+ gvfs_symlink *lnk = g_try_new0(gvfs_symlink, 1);
+
+ lnk->up(name, permissions, flags);
+
+ return (gvfs_file*)lnk;
+ }
+ void operator delete (void *p)
+ {
+ ( (gvfs_symlink*)p )->down();
+ g_free (p);
+ }
+};
+//=============================================================================
+// Async "core" structs
+//=============================================================================
+
+
+//-----------------------------------------------------------------------------
+// gvfs async part : struct_gvfs_async
+//-----------------------------------------------------------------------------
+
+struct gvfs_async_caller_data
+;
+// Function for freeing the GList and eventually freeing the data it contains
+// gvfs_async_xxx specific
+typedef void gvs_async_func_del_list(GList*);
+
+// Struct created by the gvfs async "main call" function
+// gvfs_async_xxx generic
+struct gvfs_async
+{
+ private:
+ gint32 a_handle_index;
+ gint a_max_result;
+ gvfs_async_caller_data *a_caller_data;
+ gpointer a_async_data;
+ public:
+ gint32 hi() { return a_handle_index; }
+ gvfs_async_caller_data* cd() { return a_caller_data; }
+ gint mr() { return a_max_result; }
+ gpointer& ad() { return a_async_data; }
+
+ public:
+ void* operator new (size_t size, gint32 handle_index, gint max_result, gvfs_async_caller_data* caller_data)
+ {
+ gvfs_async *ga = g_try_new0(gvfs_async, 1);
+
+ if ( !ga )
+ {
+ gwr_err("gvfs_async::new:g_try_new0 failed");
+ return ga;
+ }
+
+ // no up & down function, since we have no inheritance
+ // for this struct
+ ga->a_handle_index = handle_index;
+ ga->a_caller_data = caller_data;
+ ga->a_max_result = max_result;
+
+ return ga;
+ }
+
+ void operator delete (void *p)
+ {
+ g_free (p);
+ }
+};
+
+//-----------------------------------------------------------------------------
+// Caller part :
+// * gvfs_async_callback
+// * struct gvfs_async_caller_data
+//-----------------------------------------------------------------------------
+typedef void gvfs_async_user_callback(gvfs_async*);
+
+struct gvfs_async_caller_data
+{
+ gvfs_async_user_callback *a_callback;
+ gpointer a_user_data;
+
+ public:
+ void* operator new (size_t size, gvfs_async_user_callback callback, gpointer p)
+ {
+ gvfs_async_caller_data *cd = g_try_new0(gvfs_async_caller_data, 1);
+
+ if ( !cd )
+ {
+ gwr_err("gvfs_async_caller_data::new:g_try_new0 failed");
+ return cd;
+ }
+
+ cd->a_callback = callback;
+ cd->a_user_data = p;
+
+ return cd;
+ }
+
+ void operator delete (void *p)
+ {
+ g_free (p);
+ }
+};
+
+
+
+//=============================================================================
+// Async structs for "Load subdirectories of a directory"
+//=============================================================================
+
+//-----------------------------------------------------------------------------
+// struct helper that will updated in each GVFS callback call MULTITHREAD
+//-----------------------------------------------------------------------------
+struct gvfs_async_load_subdirs
+{
+ //.........................................................................
+ private:
+ GnomeVFSURI *m_parent_uri;
+ gchar *m_parent_path;
+ gboolean a_follow_links;
+ public:
+ GnomeVFSURI*& puri() { return m_parent_uri; }
+ gchar*& ppath() { return m_parent_path; }
+ gboolean& follow_links() { return a_follow_links; }
+
+ //.........................................................................
+ private:
+ GArray *m_array;
+ gint a_array_card;
+ public:
+ GArray*& array() { return m_array; }
+ gint& len() { return a_array_card; }
+
+ gvfs_file* element(gint i) { return g_array_index(m_array, gvfs_file*, i); }
+
+ void append(gvfs_file *file)
+ {
+ g_return_if_fail( file != NULL );
+ g_array_append_val(m_array, file);
+ a_array_card++;
+ }
+
+ public:
+ void* operator new (size_t size, GnomeVFSURI* parent_uri, gchar *parent_path) ;
+ void operator delete (void *p);
+};
+
+
+//*****************************************************************************
+// Functions
+//*****************************************************************************
+gboolean GVFS_qstack_initialized();
+void GVFS_qstack_initialize();
+
+GnomeVFSURI* GVFS_uri_new(const gchar *text);
+gboolean GVFS_info_from_uri(GnomeVFSURI* uri, GnomeVFSFileInfo* info);
+
+gboolean GVFS_vfsinfo_has_type_directory (GnomeVFSFileInfo *info);
+gboolean GVFS_vfsinfo_has_type_symlink (GnomeVFSFileInfo *info);
+
+void GVFS_async_cancel_all();
+
+void GVFS_async_load_subdirectories(
+ GnomeVFSURI *parent_uri,
+ gchar *parent_path,
+ gvfs_async_caller_data *cd,
+ gint max_result,
+ gboolean follow_links);
+
+#endif //__GCMDGTKFOLDVIEW_GVFS_H__
diff --git a/src/gnome-cmd-foldview-model.cc b/src/gnome-cmd-foldview-model.cc
new file mode 100644
index 0000000..f5381d2
--- /dev/null
+++ b/src/gnome-cmd-foldview-model.cc
@@ -0,0 +1,447 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ ---------------------------------------------------------------------------
+
+ C++
+
+ Contains variadic macros
+
+ ---------------------------------------------------------------------------
+
+ 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 option) 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <gtk/gtksignal.h>
+#include <gtk/gtkvbox.h>
+
+#include <libgnomevfs/gnome-vfs.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+
+#include "gnome-cmd-includes.h"
+#include "gnome-cmd-combo.h"
+#include "gnome-cmd-main-win.h"
+#include "gnome-cmd-style.h"
+#include "gnome-cmd-data.h"
+#include "gnome-cmd-con-home.h"
+#include "gnome-cmd-con-list.h"
+
+#include "gnome-cmd-foldview-private.h"
+#include "gnome-cmd-foldview-gvfs.h"
+
+// ***************************************************************************
+// * *
+// * Defines *
+// * *
+// ***************************************************************************
+GtkTreeIter GcmdGtkFoldview::Model::s_iter_NULL = { 0,0,0,0 };
+
+// ***************************************************************************
+// * *
+// * Helpers *
+// * *
+// ***************************************************************************
+
+
+
+
+
+// ***************************************************************************
+// * *
+// * Model ( gtkTreeStore ) *
+// * *
+// ***************************************************************************
+
+//=============================================================================
+// Create, destroy,...
+//=============================================================================
+void GcmdGtkFoldview::Model::raz_pointers()
+{
+ m_treestore = NULL;
+
+ root.m_iter.stamp = 0;
+ root.m_iter.user_data = NULL;
+ root.m_iter.user_data2 = NULL;
+ root.m_iter.user_data3 = NULL;
+ root.m_uri = NULL;
+ root.m_info = NULL;
+
+ m_con = NULL;
+}
+void GcmdGtkFoldview::Model::init_instance()
+{
+ raz_pointers();
+ create();
+}
+
+gboolean GcmdGtkFoldview::Model::create()
+{
+ m_treestore = gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_INT);
+
+ gtk_tree_sortable_set_sort_func( treesortable(), 0, GcmdGtkFoldview::Model::Compare, NULL, NULL);
+ gtk_tree_sortable_set_sort_column_id( treesortable(), 0, GTK_SORT_ASCENDING);
+
+ connection(get_home_con());
+
+ return TRUE;
+}
+void GcmdGtkFoldview::Model::destroy()
+{
+}
+
+//=============================================================================
+// alloc / free a GtkTreeIter
+//=============================================================================
+GtkTreeIter* GcmdGtkFoldview::Model::Iter_new(GtkTreeIter* iter)
+{
+ GtkTreeIter *new_iter = g_new0(GtkTreeIter,1);
+
+ if ( iter != NULL )
+ *new_iter = *iter;
+
+ return new_iter;
+}
+void GcmdGtkFoldview::Model::Iter_del(GtkTreeIter* iter)
+{
+ g_free(iter);
+}
+
+gboolean GcmdGtkFoldview::Model::iter_from_path(
+ GtkTreePath *path,
+ GtkTreeIter *iter)
+{
+ return gtk_tree_model_get_iter(
+ GcmdFoldview()->model.treemodel(),
+ iter,
+ path);
+}
+
+
+//=============================================================================
+// given an iter, return a mallocated
+// * GnomeVFSURI representing the full path
+// * gchar* representing the iter string
+// ( is GtkTreeModel sucking ??? )
+//=============================================================================
+GnomeVFSURI* GcmdGtkFoldview::Model::iter_get_uri_new(GtkTreeIter *final)
+{
+ GtkTreePath *path = NULL;
+ GnomeVFSURI *uri = NULL;
+ GtkTreeIter iter;
+ gchar strUri [1024];
+ gchar* strTemp;
+
+ strcpy(strUri,"");
+
+ // get the path from iter
+ path = gtk_tree_model_get_path( treemodel(), final );
+
+ while ( gtk_tree_path_get_depth(path) >= 1 )
+ {
+ if ( gtk_tree_model_get_iter( treemodel(), &iter, path) )
+ {
+ gtk_tree_model_get(treemodel(), &iter, 0, &strTemp, -1);
+ //gwr_inf("temp:%s", strTemp);
+ g_strreverse(strTemp);
+ g_strlcat(strUri, strTemp, 1024);
+ g_strlcat(strUri, "/", 1024);
+ g_free(strTemp);
+ }
+ gtk_tree_path_up(path);
+ }
+
+
+ // free the path
+ gtk_tree_path_free(path);
+
+ // reverse
+ g_strreverse(strUri);
+ //gwr_inf("uri_from_iter:%s", strUri);
+
+ // new uri
+ uri = GVFS_uri_new(strUri);
+ return uri;
+}
+
+gchar* GcmdGtkFoldview::Model::iter_get_string_new(GtkTreeIter *iter)
+{
+ gchar* strTemp;
+
+ gtk_tree_model_get(treemodel(), iter, 0, &strTemp, -1);
+
+ return strTemp;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+//=============================================================================
+// model for root element
+//=============================================================================
+gboolean GcmdGtkFoldview::Model::Root::set(GnomeVFSURI *uri)
+{
+ if ( ( m_uri != NULL) || ( m_info != NULL ) )
+ {
+ ERR_RET(FALSE, "model_root::set:root not empty - please first call unset");
+ }
+
+ m_info = gnome_vfs_file_info_new();
+ m_uri = GVFS_uri_new(uri->text);
+
+ if ( ( !m_uri ) || ( !m_info ) )
+ {
+ gwr_err_vfs("model_root::set:uri <%s>:failed", m_uri->text);
+ unset();
+ return FALSE;
+ }
+
+ if ( !GVFS_info_from_uri(m_uri,m_info) )
+ {
+ gwr_err("model_root::set:uri <%s>:could not get info", m_uri->text);
+ unset();
+ return FALSE;
+ }
+
+ if ( !GVFS_vfsinfo_has_type_directory(m_info) )
+ {
+ gwr_err("model_root::set:uri <%s>:is not a folder", m_uri->text);
+ unset();
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void GcmdGtkFoldview::Model::Root::unset()
+{
+ if ( m_uri )
+ {
+ gwr_inf("model_root::unset:uri not null, destroying...");
+ if ( m_uri->ref_count != 1 )
+ ERR_FAIL("model_root::unset:uri refcount is not 1:%i", m_uri->ref_count);
+ gnome_vfs_uri_unref(m_uri);
+ }
+ else
+ {
+ gwr_inf("model_root::unset:uri is null, destroying nothing");
+ }
+
+ if ( m_info )
+ {
+ gwr_inf("model_root::unset:info not null, destroying...");
+ if ( m_info->refcount != 1 )
+ ERR_FAIL("model_root::unset:infp refcount is not 1:%i", m_info->refcount);
+ gnome_vfs_file_info_unref(m_info);
+ }
+ else
+ {
+ gwr_inf("model_root::unset:info is null, destroying nothing");
+ }
+
+ m_uri = NULL;
+ m_info = NULL;
+}
+
+//=============================================================================
+// GtkTreeStore comparefunc
+//=============================================================================
+gint GcmdGtkFoldview::Model::Compare(
+ GtkTreeModel *model,
+ GtkTreeIter *iter_a,
+ GtkTreeIter *iter_b,
+ gpointer user_data)
+{
+ gchar *str_a, *str_b;
+ gboolean a_dotted = FALSE;
+ gboolean b_dotted = FALSE;
+ gint res = 0;
+
+ gtk_tree_model_get(model, iter_a, 0, &str_a, -1);
+ gtk_tree_model_get(model, iter_b, 0, &str_b, -1);
+
+ if ( str_a[0] == '.' ) a_dotted = TRUE;
+ if ( str_b[0] == '.' ) b_dotted = TRUE;
+
+ if ( a_dotted && !b_dotted )
+ {
+ g_free(str_a);
+ g_free(str_b);
+ return 1;
+ }
+
+ if ( b_dotted && !a_dotted )
+ {
+ g_free(str_a);
+ g_free(str_b);
+ return -1;
+ }
+
+ res = g_utf8_collate(str_a, str_b);
+ g_free(str_a);
+ g_free(str_b);
+ return res;
+}
+
+
+
+
+//=============================================================================
+// subfolders of an item
+//=============================================================================
+gboolean GcmdGtkFoldview::Model::iter_add_child(
+ GtkTreeIter *parent,
+ GtkTreeIter *child,
+ const gchar *name,
+ gint access)
+{
+ gtk_tree_store_append( treestore(), child, parent );
+ gtk_tree_store_set( treestore(), child, 0, name, 1, access, -1 );
+
+ /*
+ GtkTreePath *path = gtk_tree_model_get_path(treemodel(), child);
+
+ GtkTreeRowReference *row_ref = gtk_tree_row_reference_new(treemodel(),path);
+
+ row_blob_new(row_ref, NULL);
+
+ gwr_inf("--- blob list ---");
+ GList *list = g_list_first(d_blob_list);
+ while ( list )
+ {
+ gwr_inf("blob [0x%08x]", list->data);
+
+ list = g_list_next(list);
+ }
+ */
+ return TRUE;
+}
+
+//=============================================================================
+// set value for iter
+//=============================================================================
+void GcmdGtkFoldview::Model::iter_set(GtkTreeIter *iter, gchar* text, gint access)
+{
+ gtk_tree_store_set( treestore(), iter, 0, text, 1, access, -1);
+}
+
+//=============================================================================
+// set value for first child -> control
+//=============================================================================
+void GcmdGtkFoldview::Model::iter_replace_first_child(
+ GtkTreeIter *parent,
+ GtkTreeIter *child,
+ gchar* text,
+ gint access)
+{
+ if ( !gtk_tree_model_iter_children( treemodel(), child, parent) )
+ {
+ gwr_err("iter_replace_first_child:could not get first child");
+ return;
+ }
+
+ // set the value
+ iter_set( child, text, access);
+}
+
+//=============================================================================
+// set value for [DUMMY] child -> control
+// It seems that we can append rows during text_expand_row signal, but not // _GWR_GTK_01_
+// remove rows. So instead of removing [DUMMY], we replace its value...and
+// we create the model_iter_set_first_child above just for fun.
+//=============================================================================
+void GcmdGtkFoldview::Model::iter_replace_dummy_child(
+ GtkTreeIter *parent,
+ GtkTreeIter *child,
+ gchar* text,
+ gint access)
+{
+ gint n = iter_n_children(parent);
+
+ if ( n !=1 )
+ {
+ gwr_err("iter_replace_dummy_child:parent has %03i children", n);
+ return;
+ }
+ iter_replace_first_child(parent, child, text, access);
+}
+
+//=============================================================================
+// Count childs of an iter
+//=============================================================================
+gint GcmdGtkFoldview::Model::iter_n_children(GtkTreeIter *parent)
+{
+ return gtk_tree_model_iter_n_children( treemodel(), parent );
+}
+
+
+//=============================================================================
+// Remove one iter
+// Removes iter from tree_store. After being removed, iter is set to the next
+// valid row at that level, or invalidated if it previously pointed
+// to the last one.
+//=============================================================================
+gboolean GcmdGtkFoldview::Model::iter_remove(GtkTreeIter *iter)
+{
+ //gwr_inf("iter_remove");
+ return gtk_tree_store_remove( treestore(), iter);
+}
+
+
+//=============================================================================
+// Remove all children of an iter
+//=============================================================================
+gint GcmdGtkFoldview::Model::iter_remove_children(GtkTreeIter *parent)
+{
+ gint count = 0;
+ //gchar *str = NULL;
+ GtkTreeIter child;
+
+ while ( gtk_tree_model_iter_children( treemodel(), &child, parent) )
+ {
+ //str = iter_get_string_new(&child);
+ //gwr_inf("Model::iter_remove_children:child %s", str);
+ //g_free(str);
+
+ count += iter_remove_children(&child);
+
+ iter_remove(&child);
+ count ++;
+ }
+
+ return count;
+}
+
+//=============================================================================
+// Remove all
+//=============================================================================
+void GcmdGtkFoldview::Model::iter_remove_all()
+{
+ gtk_tree_store_clear(treestore());
+}
diff --git a/src/gnome-cmd-foldview-private.h b/src/gnome-cmd-foldview-private.h
new file mode 100644
index 0000000..a38c830
--- /dev/null
+++ b/src/gnome-cmd-foldview-private.h
@@ -0,0 +1,788 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ 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 option) 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GCMDGTKFOLDVIEW_PRIVATE_H__
+#define __GCMDGTKFOLDVIEW_PRIVATE_H__
+
+/******************************************************************************
+
+ C++
+ Contains variadic macros
+
+ ---------------------------------------------------------------------------
+ TODO GWR
+
+ GcmdFileSelector resize automatically resize the main vertical pane
+ ( FILL / EXPAND gtk settings somewhere ) ?
+
+ memory leaks hunt
+
+ symlinks icons show little white pixel when selected its ugly
+ but gcmd's too
+
+ init / destroy cleanup : g_object_ref on hided widgets
+
+ ..................... facultative / later ............................
+
+ sync file_list when it is not active ( in a hidden tab )
+
+ Bookmarks
+
+ Notification from filesystem ( very hard to do, we're really going
+ multithread ) -> gdk_threads_enter will be enough I think
+
+ ---------------------------------------------------------------------------
+ TODO EPIOTR
+
+ * foldview should respect global settings for case sensitive
+ sorting (gnome_cmd_data.case_sens_sort) and showing hidden dirs
+ (gnome_cmd_data.filter_settings.hidden)
+
+ * when folview is opened for the first time, it should initially
+ expand to the current dir of active pane:
+ main_win->fs(ACTIVE)->get_directory()
+
+
+
+*******************************************************************************
+ HELPERS LOGGERS
+ ===============
+
+* gnome-cmd-file.h
+gint gnome_cmd_file_get_ref_count(GnomeCmdFile* file);
+void gnome_cmd_file_log(gchar *str, GnomeCmdFile *File);
+
+gint gnome_cmd_file_get_ref_count(GnomeCmdFile* file)
+{
+ return file->priv->ref_cnt;
+}
+
+* gnome-cmd-file.cc
+void gnome_cmd_file_log(gchar *str, GnomeCmdFile *file)
+{
+ gchar temp[1024];
+
+ sprintf(temp, "fil:[0x%08x %3s][%03i-%03i] [h:xxxxxxxx] [mu:xxx] [%s] [%s]\n",
+ file,
+ g_object_is_floating(file) ? "FLO" : "REF",
+ ((GInitiallyUnowned*)file)->ref_count,
+ gnome_cmd_file_get_ref_count(file),
+ GNOME_CMD_FILE_INFO(file)->uri != NULL ? GNOME_CMD_FILE_INFO(file)->uri->text : "no uri",
+ str);
+
+ printf(temp);
+}
+
+* gnome-cmd-dir.h
+void gnome_cmd_dir_log(const gchar *str, GnomeCmdDir *dir);
+
+* gnome-cmd-dir.cc
+void gnome_cmd_dir_log(const gchar *str, GnomeCmdDir *dir)
+{
+ gchar temp[1024];
+
+ if ( ! dir )
+ {
+ sprintf(temp, "dir:NULL [%s]\n", str);
+ return;
+ }
+
+ sprintf(temp, "dir:[0x%08x %3s][%03i-%03i] [h:0x%08x] [mu:xxx] [%s] [%s]\n",
+ dir,
+ g_object_is_floating(dir) ? "FLO" : "REF",
+ ((GInitiallyUnowned*)dir)->ref_count,
+ gnome_cmd_file_get_ref_count(GNOME_CMD_FILE(dir)),
+ gnome_cmd_dir_get_handle(dir),
+ //dir->priv->monitor_users,
+ GNOME_CMD_FILE_INFO(dir)->uri != NULL ? GNOME_CMD_FILE_INFO(dir)->uri->text : "no uri",
+ str);
+
+ printf(temp);
+}
+
+* gnome-cmd-file-list.cc
+static void on_dir_list_failed (GnomeCmdDir *dir, GnomeVFSResult result, GnomeCmdFileList *fl)
+{
+ gnome_cmd_dir_log("on_dir_list_failed 00", dir);
+
+ DEBUG('l', "on_dir_list_failed\n");
+
+ if (result != GNOME_VFS_OK)
+ gnome_cmd_show_message (NULL, _("Directory listing failed."), gnome_vfs_result_to_string (result));
+
+ gnome_cmd_dir_log("on_dir_list_failed 01", dir);
+
+ g_signal_handlers_disconnect_matched (fl->cwd, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, fl);
+ gnome_cmd_dir_log("on_dir_list_failed 01-1", dir);
+ fl->connected_dir = NULL;
+ gnome_cmd_dir_log("on_dir_list_failed 01-2", dir);
+ gnome_cmd_dir_unref (fl->cwd);
+ gnome_cmd_dir_log("on_dir_list_failed 01-3", dir);
+ set_cursor_default_for_widget (*fl);
+ gnome_cmd_dir_log("on_dir_list_failed 01-4", dir);
+ gtk_widget_set_sensitive (*fl, TRUE);
+
+ gnome_cmd_dir_log("on_dir_list_failed 02", dir);
+
+ if (fl->lwd && fl->con == gnome_cmd_dir_get_connection (fl->lwd))
+ {
+ fl->cwd = fl->lwd;
+ g_signal_connect (fl->cwd, "list-ok", G_CALLBACK (on_dir_list_ok), fl);
+ g_signal_connect (fl->cwd, "list-failed", G_CALLBACK (on_dir_list_failed), fl);
+ fl->lwd = NULL;
+ }
+ else
+ g_timeout_add (1, (GSourceFunc) set_home_connection, fl);
+}
+
+void GnomeCmdFileList::set_connection (GnomeCmdCon *new_con, GnomeCmdDir *start_dir)
+{
+ g_return_if_fail (GNOME_CMD_IS_CON (new_con));
+
+ if (con==new_con)
+ {
+ //if (!gnome_cmd_con_should_remember_dir (new_con)) //original code buggy // __GWR__MARK__
+ if ( gnome_cmd_con_should_remember_dir (new_con))
+ set_directory (gnome_cmd_con_get_default_dir (new_con));
+ else
+ if (start_dir)
+ set_directory (start_dir);
+ return;
+ }
+ ...
+
+void GnomeCmdFileList::set_directory(GnomeCmdDir *dir)
+{
+ g_return_if_fail (GNOME_CMD_IS_DIR (dir));
+
+ gnome_cmd_dir_log("GnomeCmdFileList::set_directory 00", dir);
+
+ if (cwd==dir)
+ return;
+
+ if (realized && dir->state!=DIR_STATE_LISTED)
+ {
+ gtk_widget_set_sensitive (*this, FALSE);
+ set_cursor_busy_for_widget (*this);
+ }
+
+ gnome_cmd_dir_ref (dir);
+
+ if (lwd && lwd!=dir)
+ gnome_cmd_dir_unref (lwd);
+
+ if (cwd)
+ {
+ gnome_cmd_dir_cancel_monitoring (cwd);
+ lwd = cwd;
+ g_signal_handlers_disconnect_matched (lwd, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, this);
+ cwd->voffset = gnome_cmd_clist_get_voffset (*this);
+ }
+
+ cwd = dir;
+
+ switch (dir->state)
+ {
+ case DIR_STATE_EMPTY:
+ g_signal_connect (dir, "list-ok", G_CALLBACK (on_dir_list_ok), this);
+ g_signal_connect (dir, "list-failed", G_CALLBACK (on_dir_list_failed), this);
+ gnome_cmd_dir_log("GnomeCmdFileList::set_directory 01", dir);
+ gnome_cmd_dir_list_files (dir, gnome_cmd_con_needs_list_visprog (con));
+ gnome_cmd_dir_log("GnomeCmdFileList::set_directory 02", dir);
+ break;
+
+ case DIR_STATE_LISTING:
+ case DIR_STATE_CANCELING:
+ g_signal_connect (dir, "list-ok", G_CALLBACK (on_dir_list_ok), this);
+ g_signal_connect (dir, "list-failed", G_CALLBACK (on_dir_list_failed), this);
+ break;
+
+ case DIR_STATE_LISTED:
+ on_dir_list_ok (dir, NULL, this);
+ gnome_cmd_dir_start_monitoring (dir);
+ break;
+ }
+
+ gnome_cmd_dir_log("GnomeCmdFileList::set_directory 03", dir);
+
+ // in the previous 'case', dir->state may have been modified. So include
+ // this line in the 'case'
+ //gnome_cmd_dir_start_monitoring (dir);
+}
+
+
+
+*******************************************************************************
+
+ WIDGET HIERARCHY FOR GTK-FOLDVIEW
+ =================================
+
+ vbox
+ |
+ con_hbox
+ | |
+ | +-----------GtkWidget *con_combo ---------- GtkWidget *vol_label;
+ |
+ |
+ dir_indicator
+ |
+ scrolled window-------- treeview
+ |
+ GtkWidget *info_label;
+
+
+*******************************************************************************
+
+ WIDGET HIERARCHY FOR GNOME-CMD-FILE-SELECTOR
+ ============================================
+
+ vbox
+ |
+ GnomeCmdFileSelector
+ |
+ |
+ +--------------------- GnomeCmdFileList
+
+
+*******************************************************************************
+
+ GTK+ DRAG & DROP SYNOPSIS
+ =========================
+
+
+ "drag-begin" SRC
+
+ "drag-motion" DST
+ |
+ |
+ +-----------------------+
+ | |
+ | |
+ "drag-drop" "drag-leave" DST
+ |
+ |
+ "drag-data-get" SRC
+ |
+ |
+ "drag-data-received" DST
+ |
+ |
+ "drag-end" SRC
+
+
+ + "drag-failed" SRC
+ "drag-data-delete" SRC
+
+******************************************************************************/
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtklabel.h>
+
+#define GCMDGTKFOLDVIEW_TYPE (gcmdgtkfoldview_get_type ())
+#define GCMDGTKFOLDVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCMDGTKFOLDVIEW_TYPE, GcmdGtkFoldview))
+#define GCMDGTKFOLDVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GCMDGTKFOLDVIEW_TYPE, GcmdGtkFoldviewClass))
+#define IS_GCMDGTKFOLDVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCMDGTKFOLDVIEW_TYPE))
+#define IS_GCMDGTKFOLDVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GCMDGTKFOLDVIEW_TYPE))
+
+//*****************************************************************************
+// Logging
+//*****************************************************************************
+#define DEBUG_SHOW_INF
+#define DEBUG_SHOW_WNG
+#define DEBUG_SHOW_ERR
+#define DEBUG_SHOW_VFS
+
+void gwr_print(const char* str);
+
+void gwr_inf(const char* fmt, ...);
+void gwr_wng(const char* fmt, ...);
+void gwr_err(const char* fmt, ...);
+
+void gwr_inf_vfs(const char* fmt, ...);
+void gwr_err_vfs(const char* fmt, ...);
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Facilities logging
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+#define ERR_RET(value,...) \
+{ \
+ gwr_err(__VA_ARGS__); \
+ return value; \
+}
+
+#define ERR_FAIL(...) \
+{ \
+ gwr_err(__VA_ARGS__); \
+ exit(1); \
+}
+//---------------------------------------------------------------------------
+#define ERR_VFS_RET(value,...) \
+{ \
+ if ( sVFSResult != GNOME_VFS_OK ) \
+ { \
+ gwr_err_vfs(__VA_ARGS__); \
+ return value; \
+ } \
+}
+
+#define ERR_VFS_FAIL(value,...) \
+{ \
+ if ( sVFSResult != GNOME_VFS_OK ) \
+ { \
+ gwr_err_vfs(__VA_ARGS__); \
+ exit(1); \
+ } \
+}
+
+
+//*****************************************************************************
+// GcmdGtkFoldview
+//*****************************************************************************
+
+struct gvfs_async;
+struct gvfs_file;
+
+struct GcmdGtkFoldview
+{
+ //=========================================================================
+ // Widgets and gtk inheritance
+ //=========================================================================
+ GtkVBox vbox;
+
+ //=========================================================================
+ // Common data, enum, typedefs
+ //=========================================================================
+ public:
+
+ enum eFileAccess
+ {
+ // these permissions are user-relatives ( the user that launched gcmd )
+ eAccessReadOnly = 0 ,
+ eAccessReadWrite = 1 ,
+ eAccessForbidden = 2 ,
+
+ eAccessInit = 0xFE,
+ eAccessUnknown = 0xFF
+
+ };
+
+
+ public:
+ static eFileAccess Access_from_permissions (GnomeVFSFilePermissions permissions);
+
+
+ //=========================================================================
+ // View
+ //=========================================================================
+ struct View
+ {
+ // For fixing the moving gutter of the pane
+ gulong a_size_request_handle;
+ gint a_size_request_width;
+
+ // We have a m_parent member because of callbacks, for calling
+ // the controller
+ private:
+ GtkWidget *a_this;
+
+ //---------------------------------------------------------------------
+ // other widgets ( we are a composite widget )
+ //---------------------------------------------------------------------
+ private:
+ GtkWidget *m_con_hbox;
+ GtkWidget *m_con_combo;
+ GtkWidget *m_vol_label;
+
+ // __GWR__ Unable to reuse the gnome-cmd-dir-indicator since it is
+ // crossed with gnome-cmd-file-selector
+ GtkWidget m_dir_indicator;
+
+ GtkWidget *m_scrolledwindow;
+ GtkWidget *m_info_label;
+
+ public:
+ GcmdGtkFoldview *foldview() { return (GcmdGtkFoldview*)a_this; }
+ GtkWidget *connection_combo() { return (m_con_combo); }
+
+ //---------------------------------------------------------------------
+ // icons
+ //---------------------------------------------------------------------
+ private:
+ GdkPixbuf *m_pixbuf[50];
+
+ public:
+ enum eIcon
+ {
+ eIconUnknown ,
+
+ eIconDirReadWrite ,
+ eIconDirReadOnly ,
+ eIconDirForbidden ,
+
+ eIconSymlinkToDirReadWrite ,
+ eIconSymlinkToDirReadOnly ,
+ eIconSymlinkToDirForbidden
+ };
+
+ private:
+ gboolean icons_load();
+ void icons_unload();
+
+ public:
+ GdkPixbuf *pixbuf(eIcon icon) { return m_pixbuf[icon]; }
+
+ static eIcon Icon_from_type_permissions (GnomeVFSFileType type, GnomeVFSFilePermissions permissions);
+ static eIcon Icon_from_type_access (GnomeVFSFileType type, GcmdGtkFoldview::eFileAccess access);
+
+ //---------------------------------------------------------------------
+ // connection combo
+ //---------------------------------------------------------------------
+ public:
+ void connection_combo_add_connection(GnomeCmdCon *con);
+ void connection_combo_reset();
+
+ //---------------------------------------------------------------------
+ // gtk treeview ( main view )
+ //---------------------------------------------------------------------
+ private:
+ GtkWidget *m_treeview;
+ GtkTreeModel *m_treemodel;
+
+ GtkTreeView *treeview() { return GTK_TREE_VIEW (m_treeview); }
+
+ public:
+ void init_instance(GtkWidget *_this, GtkTreeModel *_treemodel);
+ private:
+ void raz_pointers();
+ gboolean create(GtkWidget *_this, GtkTreeModel *_treemodel);
+ void destroy();
+
+ private:
+ GtkTreeSelection *selection() { return gtk_tree_view_get_selection(treeview()); }
+ gint selection_count()
+ {
+ // Note: gtk_tree_selection_count_selected_rows() does not
+ // exist in gtk+-2.0, only in gtk+ >= v2.2 !
+ return gtk_tree_selection_count_selected_rows(selection());
+ }
+
+ //.....................................................................
+ static gboolean signal_test_expand_row(GtkTreeView *tree_view,
+ GtkTreeIter *iter, GtkTreePath *path, gpointer user_data);
+
+ static void signal_row_expanded(GtkTreeView *tree_view,
+ GtkTreeIter *iter, GtkTreePath *path, gpointer user_data);
+
+ static void signal_row_collapsed(GtkTreeView *tree_view,
+ GtkTreeIter *iter, GtkTreePath *path,gpointer user_data);
+
+ static gboolean signal_button_press_event(GtkWidget *tree_view,
+ GdkEventButton *event, gpointer user_data);
+
+ static void signal_drag_begin(GtkWidget *widget,
+ GdkDragContext *drag_context, gpointer user_data);
+
+ static void signal_size_request(GtkWidget *widget,
+ GtkRequisition *requisition,gpointer data);
+
+ //---------------------------------------------------------------------
+ // contextual menu
+ //---------------------------------------------------------------------
+ public:
+ struct ctx_menu_data
+ {
+ GcmdGtkFoldview *a_foldview;
+ GtkTreePath *d_path_clicked;
+ GtkTreePath *d_path_selected;
+ guint32 a_time;
+ gint a_event_x;
+ gint a_event_y;
+ guint a_button;
+
+ ~ctx_menu_data()
+ {
+ if ( d_path_selected )
+ {
+ gtk_tree_path_free(d_path_selected);
+ }
+ if ( d_path_clicked )
+ {
+ gtk_tree_path_free(d_path_clicked);
+ }
+ }
+
+ void *operator new(size_t size) { return g_new0(ctx_menu_data, 1); }
+ void operator delete(void *p) { g_free(p); }
+ };
+ public:
+ struct ctx_menu_desc
+ {
+ gboolean a_connect;
+ gchar *a_text;
+ GCallback a_callback;
+ };
+ struct ctx_menu_entry
+ {
+ ctx_menu_desc a_desc;
+ GtkWidget *a_widget;
+ gulong a_handle;
+ };
+ struct ctx_menu_section
+ {
+ gchar *a_title;
+ gint a_card;
+ ctx_menu_entry a_entry[5];
+ };
+ struct ctx_menu
+ {
+ GtkWidget *a_widget;
+ gint a_card;
+ ctx_menu_section a_section[5];
+ };
+
+ private:
+ gboolean context_menu_pop(ctx_menu_data*);
+
+ gboolean click_left_single(ctx_menu_data *ctxdata);
+ gboolean click_left_double(ctx_menu_data *ctxdata);
+
+ //---------------------------------------------------------------------
+ // Theming
+ //---------------------------------------------------------------------
+ public:
+ void update_style();
+
+ } view;
+ //=========================================================================
+ // Model
+ //=========================================================================
+ struct Model
+ {
+ public:
+ void init_instance();
+ private:
+ void raz_pointers();
+ gboolean create();
+ void destroy(); // __GWR__TODO__
+
+ //---------------------------------------------------------------------
+ // divers
+ //---------------------------------------------------------------------
+ public:
+ static GtkTreeIter s_iter_NULL;
+
+ //---------------------------------------------------------------------
+ // gtk treestore
+ //---------------------------------------------------------------------
+ private:
+ GtkTreeStore *m_treestore;
+ public:
+ GtkTreeStore *treestore() { return m_treestore; }
+ GtkTreeModel *treemodel() { return GTK_TREE_MODEL(m_treestore); }
+ GtkTreeSortable *treesortable() { return GTK_TREE_SORTABLE(m_treestore);}
+
+ private:
+ static gint Compare(GtkTreeModel*, GtkTreeIter*, GtkTreeIter* , gpointer);
+ public:
+ static GtkTreeIter* Iter_new(GtkTreeIter*);
+ static void Iter_del(GtkTreeIter*);
+
+ gboolean iter_from_path (GtkTreePath *path /*in*/, GtkTreeIter *iter /*out*/);
+ GnomeVFSURI* iter_get_uri_new (GtkTreeIter *iter);
+ gchar* iter_get_string_new (GtkTreeIter *iter);
+
+ void iter_set(GtkTreeIter*, gchar*, gint access);
+ void iter_replace_first_child(GtkTreeIter *parent, GtkTreeIter *child, gchar *name, gint access);
+ void iter_replace_dummy_child(GtkTreeIter *parent, GtkTreeIter *child, gchar *name, gint access);
+ gboolean iter_add_child(GtkTreeIter* parent /*in*/, GtkTreeIter *child /*out*/, const gchar *name, gint access);
+
+ gint iter_n_children(GtkTreeIter *parent);
+ gboolean iter_remove(GtkTreeIter *iter);
+ void iter_remove_all();
+
+ private:
+ gint iter_remove_children_recurse(GtkTreeIter *parent);
+ public:
+ gint iter_remove_children(GtkTreeIter *parent);
+
+ //---------------------------------------------------------------------
+ // store custom data in gtktreestore !
+ //---------------------------------------------------------------------
+ private:
+ struct row_blob
+ {
+ public:
+ GtkTreeRowReference *d_row_ref;
+
+ gvfs_file *d_file;
+
+ };
+ GList *d_blob_list;
+
+ public:
+ //void row_blob_remove_unvalids();
+ //row_blob* row_blob_find(GtkTreeRowReference *row_ref);
+ void row_blob_new(GtkTreeRowReference *row_ref, gvfs_file *file)
+ {
+ if ( !row_ref )
+ return;
+
+ row_blob *rb = g_try_new0(row_blob,1);
+
+ rb->d_row_ref = row_ref;
+ rb->d_file = NULL;
+
+ d_blob_list = g_list_append(d_blob_list, (gpointer)rb);
+ }
+ //---------------------------------------------------------------------
+ // root element ( because of samba possibility )
+ //---------------------------------------------------------------------
+ public:
+ struct Root
+ {
+ GtkTreeIter m_iter;
+ GnomeVFSURI *m_uri;
+ GnomeVFSFileInfo *m_info; // __GWR_TODO__ gnome_vfs_dup segfault ???
+ gboolean set(GnomeVFSURI *uri);
+ void unset();
+ } root;
+
+ //---------------------------------------------------------------------
+ // gnome-cmd-connection
+ //---------------------------------------------------------------------
+ private:
+ GnomeCmdCon *m_con;
+
+ public:
+ void connection(GnomeCmdCon *con) { m_con = con; }
+ GnomeCmdCon* connection() { return m_con; }
+
+ } model;
+
+ //=========================================================================
+ // Controller
+ //=========================================================================
+ public:
+ void control_init_instance();
+ private:
+ void control_raz_pointers();
+ gboolean control_create();
+ void control_destroy();
+
+ //-------------------------------------------------------------------------
+ // divers
+ //-------------------------------------------------------------------------
+ private:
+ gboolean control_root_uri_set(GnomeVFSURI *uri);
+
+ void control_gcmd_file_list_set_connection(GnomeCmdFileList*, GnomeVFSURI*);
+
+ void control_connection_combo_update();
+
+ //-------------------------------------------------------------------------
+ // expand / collapse
+ //-------------------------------------------------------------------------
+ public:
+ void control_iter_collapsed(GtkTreeIter *parent);
+
+ private:
+ static void control_check_if_empty_callback_1(gvfs_async*);
+ void control_check_if_empty_p(GnomeVFSURI *parent_uri, gchar *parent_path);
+ public:
+ void control_check_if_empty(GtkTreeIter *parent);
+
+ private:
+ static void control_iter_expand_callback_1(gvfs_async*);
+ static void control_iter_expand_callback_2(gvfs_async*);
+ void control_iter_expand_p(GnomeVFSURI *parent_uri, gchar *parent_path);
+ public:
+ void control_iter_expand(GtkTreeIter *parent);
+
+ //-------------------------------------------------------------------------
+ // context menu actions
+ //-------------------------------------------------------------------------
+ private:
+ void control_set_active_tab (GtkTreePath *path);
+ void control_open_new_tab (GtkTreePath *path);
+ void control_set_new_root (GcmdGtkFoldview::View::ctx_menu_data*);
+ public:
+ static void Control_set_active_tab (GtkMenuItem*, View::ctx_menu_data*);
+ static void Control_open_new_tab (GtkMenuItem*, View::ctx_menu_data*);
+ static void Control_set_new_root (GtkMenuItem*, View::ctx_menu_data*);
+
+ private:
+ enum eSyncState
+ {
+ SYNC_Y_LIST_Y,
+ SYNC_Y_LIST_N,
+ SYNC_N_LIST_Y,
+ SYNC_N_LIST_N
+ };
+ eSyncState control_sync_check ();
+ private:
+ void control_sync_treeview (GcmdGtkFoldview::View::ctx_menu_data*);
+ void control_unsync_treeview ();
+ void control_sync_update (GcmdGtkFoldview::View::ctx_menu_data*);
+ public:
+ static void Control_sync_treeview (GtkMenuItem*, View::ctx_menu_data*);
+ static void Control_unsync_treeview (GtkMenuItem*, View::ctx_menu_data*);
+ static void Control_sync_update (GtkMenuItem*, View::ctx_menu_data*);
+
+ private:
+ GnomeCmdFileList *a_synced_list;
+ gboolean a_synced;
+
+ private:
+ static View::ctx_menu s_context_menu;
+
+ public:
+ void control_context_menu_populate_add_separator(GtkWidget *widget);
+ void control_context_menu_populate_add_section(GtkWidget *widget, gint i, View::ctx_menu_data *ctxdata);
+
+ //=========================================================================
+ // Interface
+ //=========================================================================
+ public:
+ gboolean root_uri_set_1(gchar *text);
+ gboolean root_uri_set_2(GnomeVFSURI *uri);
+};
+
+GType gcmdgtkfoldview_get_type ();
+GtkWidget* gcmdgtkfoldview_new ();
+void gcmdgtkfoldview_clear (GcmdGtkFoldview *foldview);
+
+//*****************************************************************************
+// GcmdGtkFoldviewClass
+//*****************************************************************************
+struct GcmdGtkFoldviewClass
+{
+ GtkVBoxClass parent_class;
+
+ void (* gcmdgtkfoldview) (GcmdGtkFoldview* fv);
+};
+
+GcmdGtkFoldview *GcmdFoldview();
+GtkWidget *GcmdWidget();
+
+#endif //__GCMDGTKFOLDVIEW_PRIVATE_H__
diff --git a/src/gnome-cmd-foldview-view.cc b/src/gnome-cmd-foldview-view.cc
new file mode 100644
index 0000000..9512a19
--- /dev/null
+++ b/src/gnome-cmd-foldview-view.cc
@@ -0,0 +1,701 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ ---------------------------------------------------------------------------
+
+ C++
+
+ Contains variadic macros
+
+ ---------------------------------------------------------------------------
+
+ 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 option) 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <libgnomevfs/gnome-vfs.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+
+#include "gnome-cmd-includes.h"
+
+#include "gnome-cmd-combo.h"
+#include "gnome-cmd-con-device.h"
+#include "gnome-cmd-con-smb.h"
+#include "gnome-cmd-con-list.h"
+
+#include "gnome-cmd-main-win.h"
+#include "gnome-cmd-style.h"
+#include "gnome-cmd-data.h"
+
+#include "gnome-cmd-foldview-private.h"
+
+// ***************************************************************************
+// * *
+// * Defines *
+// * *
+// ***************************************************************************
+
+// ***************************************************************************
+// * *
+// * Helpers *
+// * *
+// ***************************************************************************
+
+
+// ***************************************************************************
+// * *
+// * View ( GtkTreeview ) implementation *
+// * *
+// ***************************************************************************
+static void
+myfunc(
+ GtkTreeViewColumn *col,
+ GtkCellRenderer *renderer,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ gpointer user_data)
+{
+ gint icon;
+
+ gtk_tree_model_get(model, iter, 1, &icon, -1);
+
+ g_object_set(renderer, "pixbuf", GcmdFoldview()->view.pixbuf( (GcmdGtkFoldview::View::eIcon) icon), NULL);
+}
+
+//=============================================================================
+// init_instance, ...
+//=============================================================================
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// icons
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gboolean GcmdGtkFoldview::View::icons_load()
+{
+ GError *error = NULL;
+
+ m_pixbuf[eIconUnknown] = gdk_pixbuf_new_from_file("../pixmaps/file-type-icons/file_type_unknown.xpm", &error);
+
+ m_pixbuf[eIconDirReadWrite] = gdk_pixbuf_new_from_file("../pixmaps/file-type-icons/file_type_dir.xpm", &error);
+ m_pixbuf[eIconDirReadOnly] = gdk_pixbuf_new_from_file("../pixmaps/file-type-icons/file_type_dir_orange.xpm", &error);
+ m_pixbuf[eIconDirForbidden] = gdk_pixbuf_new_from_file("../pixmaps/file-type-icons/file_type_dir_red.xpm", &error);
+
+ m_pixbuf[eIconSymlinkToDirReadWrite] = gdk_pixbuf_new_from_file("../pixmaps/file-type-icons/file_type_symlink_to_dir_green.xpm", &error);
+ m_pixbuf[eIconSymlinkToDirReadOnly] = gdk_pixbuf_new_from_file("../pixmaps/file-type-icons/file_type_symlink_to_dir_orange.xpm", &error);
+ m_pixbuf[eIconSymlinkToDirForbidden] = gdk_pixbuf_new_from_file("../pixmaps/file-type-icons/file_type_symlink_to_dir_red.xpm", &error);
+
+ return TRUE;
+}
+
+void GcmdGtkFoldview::View::icons_unload()
+{
+ g_object_unref(m_pixbuf[eIconUnknown] );
+
+ g_object_unref(m_pixbuf[eIconDirReadWrite] );
+ g_object_unref(m_pixbuf[eIconDirReadOnly] );
+ g_object_unref(m_pixbuf[eIconDirForbidden] );
+
+ g_object_unref(m_pixbuf[eIconSymlinkToDirReadWrite] );
+ g_object_unref(m_pixbuf[eIconSymlinkToDirReadOnly] );
+ g_object_unref(m_pixbuf[eIconSymlinkToDirForbidden] );
+
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// init_instance
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void GcmdGtkFoldview::View::init_instance(GtkWidget *_this, GtkTreeModel *_treemodel)
+{
+ raz_pointers();
+ create(_this, _treemodel);
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// init
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void GcmdGtkFoldview::View::raz_pointers()
+{
+ a_size_request_handle = 0;
+ a_size_request_width = 65;
+
+ m_con_hbox = NULL;
+ m_con_combo = NULL;
+ m_vol_label = NULL;
+ m_scrolledwindow = NULL;
+ m_info_label = NULL;
+
+ m_treeview = NULL;
+ m_treemodel = NULL;
+
+ for ( gint i = 0 ; i != 50 ; i++ ) m_pixbuf[i] = NULL;
+
+ a_this = NULL;
+}
+
+
+void signal_cursor_changed(
+ GtkTreeView *tree_view,
+ gpointer user_data)
+{
+ GtkTreeSelection *tree_sel = NULL;
+ gint tree_sel_card = 0;
+
+ GtkTreeIter iter_selected = GcmdGtkFoldview::Model::s_iter_NULL;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // gwr_inf("signal_cursor_changed");
+
+ // get path to currently selected iter
+ tree_sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
+ if ( ! tree_sel )
+ {
+ gwr_err("View::signal_cursor_changed:gtk_tree_view_get_selection failed");
+ }
+
+ // Note: gtk_tree_selection_count_selected_rows() does not exist in gtk+-2.0, only in gtk+ >= v2.2 !
+ tree_sel_card = gtk_tree_selection_count_selected_rows(tree_sel);
+
+ if ( tree_sel_card == 1 )
+ {
+ if ( gtk_tree_selection_get_selected( tree_sel, NULL, &iter_selected) )
+ {
+ }
+ else
+ {
+ gwr_wng("View::signal_cursor_changed:gtk_tree_selection_get_selected failed");
+ }
+ }
+ else
+ {
+ gwr_err("View::signal_cursor_changed");
+ }
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// create / destroy
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gboolean GcmdGtkFoldview::View::create(GtkWidget *_this, GtkTreeModel *_treemodel)
+{
+ m_treemodel = _treemodel;
+ a_this = _this;
+
+ //-------------------------------------------------------------------------
+ // create composite widgets
+ gtk_box_set_homogeneous(GTK_BOX(foldview()), FALSE);
+
+ // create the box used for packing the con_combo and information
+ m_con_hbox = create_hbox (GTK_WIDGET(foldview()), FALSE, 2);
+ gtk_box_set_homogeneous(GTK_BOX(m_con_hbox), FALSE);
+
+ // create the connection combo
+ m_con_combo = (GtkWidget*)( new GnomeCmdCombo(2, 1, NULL) );
+
+ gtk_object_set_data_full (GTK_OBJECT (foldview()), "con_combo", m_con_combo, (GtkDestroyNotify) g_object_unref);
+ gtk_widget_set_size_request (m_con_combo, 150, -1);
+ gtk_clist_set_row_height (GTK_CLIST (GNOME_CMD_COMBO (m_con_combo)->list), 20);
+ gtk_entry_set_editable (GTK_ENTRY (GNOME_CMD_COMBO (m_con_combo)->entry), FALSE);
+ gtk_clist_set_column_width (GTK_CLIST (GNOME_CMD_COMBO (m_con_combo)->list), 0, 20);
+ gtk_clist_set_column_width (GTK_CLIST (GNOME_CMD_COMBO (m_con_combo)->list), 1, 60);
+ GTK_WIDGET_UNSET_FLAGS (GNOME_CMD_COMBO (m_con_combo)->button, GTK_CAN_FOCUS);
+
+ // create the free space on volume label
+ //m_vol_label = gtk_label_new ("* LABEL *");
+ //g_object_ref (m_vol_label);
+ //gtk_object_set_data_full (GTK_OBJECT (m_this), "vol_label", m_vol_label, (GtkDestroyNotify) g_object_unref);
+ //gtk_misc_set_alignment (GTK_MISC (m_vol_label), 1, 0.5);
+
+ // __GWR__ Unable to reuse the gnome-cmd-dir-indicator since it is
+ // crossed with gnome-cmd-file-selector
+ // create the directory indicator
+ //m_dir_indicator = gnome_cmd_dir_indicator_new(m_dir_indicator);
+ //g_object_ref (m_dir_indicator);
+ //gtk_object_set_data_full (GTK_OBJECT (foldview),
+ // "dir_indicator", m_dir_indicator,
+ // (GtkDestroyNotify) g_object_unref);
+
+ // create the info label
+ //m_info_label = gtk_label_new ("not initialized");
+ //g_object_ref(m_info_label);
+ //gtk_object_set_data_full (GTK_OBJECT (m_this), "infolabel", m_info_label,
+ // (GtkDestroyNotify) g_object_unref);
+ //gtk_misc_set_alignment (GTK_MISC (m_info_label), 0.0f, 0.5f);
+
+ // create the scrollwindow that we'll place the treeview in
+ m_scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
+ gtk_object_set_data_full (GTK_OBJECT (foldview()),
+ "scrolledwindow", m_scrolledwindow,
+ (GtkDestroyNotify) g_object_unref);
+ gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (m_scrolledwindow),
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+
+ // create the pane that will be inserted in
+ // done in gnome-cmd-main-win.cc now
+
+ //-------------------------------------------------------------------------
+ // create the treeview
+ GtkTreeViewColumn *col0 = NULL;
+ GtkTreeViewColumn *col1 = NULL;
+ GtkCellRenderer *renderer = NULL;
+
+ icons_load();
+
+ m_treeview = gtk_tree_view_new();
+
+ // Drag & Drop
+ //
+ // void gtk_tree_view_enable_model_drag_source(
+ // GtkTreeView *tree_view,
+ // GdkModifierType start_button_mask,
+ // const GtkTargetEntry *targets,
+ // gint n_targets,
+ // GdkDragAction actions);
+ //
+ // typedef struct
+ // {
+ // gchar *target;
+ // guint flags;
+ // guint info;
+ // }
+ // GtkTargetEntry;
+ //
+ // typedef enum
+ // {
+ // GTK_TARGET_SAME_APP = 1 << 0, /*< nick=same-app >*/
+ // GTK_TARGET_SAME_WIDGET = 1 << 1 /*< nick=same-widget >*/
+ // }
+ // GtkTargetFlags;
+
+ //GtkTargetEntry drag_source_entry[2] =
+ // {
+ // { (gchar*)"text/plain", 0, 0X30 },
+ // { (gchar*)"text/plain", 0, 0X31 }
+ // };
+
+ //gtk_tree_view_enable_model_drag_source(
+ // treeview(),
+ // GDK_BUTTON1_MASK,
+ // drag_source_entry,
+ // 2,
+ // GDK_ACTION_PRIVATE );
+
+ //g_signal_connect(m_treeview, "drag-begin", G_CALLBACK (signal_drag_begin), (gpointer)this);
+
+ // columns
+ col0 = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(col0, _("Folders"));
+ gtk_tree_view_column_set_visible(col0,TRUE);
+
+ col1 = gtk_tree_view_column_new();
+ gtk_tree_view_column_set_title(col1, _("Access Rights"));
+ gtk_tree_view_column_set_visible(col1,FALSE);
+
+ // column 0 - pixbuf renderer
+ renderer = gtk_cell_renderer_pixbuf_new();
+ gtk_tree_view_column_pack_start(col0, renderer, FALSE);
+ g_object_set(renderer, "xalign", 0.0, NULL);
+ gtk_tree_view_column_set_cell_data_func(col0, renderer, myfunc, NULL, NULL);
+
+ // column 0 - text renderer
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(col0, renderer, FALSE);
+ gtk_tree_view_column_add_attribute(col0, renderer, "text", 0);
+ g_object_set(renderer, "xalign", 0.0, NULL);
+
+ // column 1 - text renderer
+ renderer = gtk_cell_renderer_text_new();
+ gtk_tree_view_column_pack_start(col1, renderer, TRUE);
+ gtk_tree_view_column_add_attribute(col1, renderer, "text", 1);
+ g_object_set(renderer, "xalign", 0.0, NULL);
+
+ gtk_tree_view_append_column(GTK_TREE_VIEW(m_treeview), col0);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(m_treeview), col1);
+
+ // signals
+ g_signal_connect(m_treeview, "test_expand_row", G_CALLBACK(signal_test_expand_row), NULL);
+ g_signal_connect(m_treeview, "row_expanded", G_CALLBACK(signal_row_expanded), NULL);
+ g_signal_connect(m_treeview, "row_collapsed", G_CALLBACK(signal_row_collapsed), NULL);
+
+ g_signal_connect(m_treeview, "button-press-event", G_CALLBACK(signal_button_press_event), foldview());
+
+ g_signal_connect(m_treeview, "cursor-changed", G_CALLBACK(signal_cursor_changed), NULL);
+
+ // some settings
+ gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(m_treeview), FALSE);
+ gtk_tree_view_set_model(GTK_TREE_VIEW(m_treeview), m_treemodel);
+ gtk_tree_view_set_show_expanders(treeview(), TRUE);
+
+ // treeview contextual menu :
+ // since we do a dynamic menu, and there is no menu_shell_remove()
+ // function in gtk, we must create it on the fly, during the
+ // callback for single-right-click
+
+ //-------------------------------------------------------------------------
+ // pack
+ gtk_box_pack_start(GTK_BOX(m_con_hbox), m_con_combo, FALSE, FALSE, 0);
+ //gtk_box_pack_start (GTK_BOX(m_con_hbox), m_vol_label, FALSE, FALSE, 0);
+
+ //gtk_box_pack_start (GTK_BOX (m_con_hbox), m_dir_indicator, FALSE, FALSE, 0);
+ //padding = create_hbox (*fs, FALSE, 6);
+ //gtk_box_pack_start (GTK_BOX (vbox), padding, FALSE, TRUE, 0);
+ //gtk_box_pack_start (GTK_BOX (padding), info_label, FALSE, TRUE, 6);
+
+ gtk_box_pack_start(GTK_BOX(foldview()), m_con_hbox, FALSE, FALSE, 0);
+ gtk_box_pack_start(GTK_BOX(foldview()), m_scrolledwindow, TRUE, TRUE, 0);
+
+ gtk_container_add(GTK_CONTAINER(m_scrolledwindow), m_treeview);
+
+ //-------------------------------------------------------------------------
+ // ref objects for showing / hiding since I dont understand gtk ref / unref
+ g_object_ref(foldview());
+
+ g_object_ref(m_con_hbox);
+ g_object_ref(m_con_combo);
+ //g_object_ref(m_dir_indicator);
+ //g_object_ref(m_vol_label);
+ g_object_ref(m_scrolledwindow);
+ g_object_ref(m_treeview);
+
+ //-------------------------------------------------------------------------
+ // show, except the pane container
+
+ //fs->update_concombo_visibility();
+ gtk_widget_show(m_con_combo);
+ //gtk_widget_show(m_vol_label);
+ //gtk_widget_show(m_info_label);
+ //gtk_widget_show (m_dir_indicator);
+ //gtk_widget_show (fs->list_widget);
+ gtk_widget_show(m_treeview);
+
+ gtk_widget_show(m_scrolledwindow);
+
+ gtk_widget_show(GTK_WIDGET(foldview()));
+
+ return TRUE;
+}
+
+void GcmdGtkFoldview::View::destroy()
+{
+}
+
+//=============================================================================
+// gtk signals
+//=============================================================================
+
+// row about to be expanded : FALSE = allow , TRUE = deny
+gboolean
+GcmdGtkFoldview::View::signal_test_expand_row(
+ GtkTreeView *tree_view,
+ GtkTreeIter *iter,
+ GtkTreePath *path,
+ gpointer user_data)
+{
+ //gwr_inf("view:signal [test_expand_row]");
+
+ GcmdFoldview()->control_iter_expand(iter);
+
+ // Allow expansion
+ return FALSE;
+}
+
+// row expanded
+void GcmdGtkFoldview::View::signal_row_expanded(
+ GtkTreeView *tree_view,
+ GtkTreeIter *iter,
+ GtkTreePath *path,
+ gpointer user_data)
+{
+ //gwr_inf("view:signal [row_expanded]");
+}
+
+// row collapsed
+void GcmdGtkFoldview::View::signal_row_collapsed(
+ GtkTreeView *tree_view,
+ GtkTreeIter *iter,
+ GtkTreePath *path,
+ gpointer user_data)
+{
+ //gwr_inf("view:signal [row_collapsed]");
+
+ GcmdFoldview()->control_iter_collapsed(iter);
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Buttons
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+gboolean GcmdGtkFoldview::View::signal_button_press_event(
+ GtkWidget *tree_view,
+ GdkEventButton *event,
+ gpointer data)
+{
+ // signal handled : return TRUE
+ // signal not handled : return FALSE
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ GtkTreePath *path_clicked = NULL;
+
+ GtkTreeIter iter_selected = GcmdGtkFoldview::Model::s_iter_NULL;
+ GtkTreePath *path_selected = NULL;
+
+ GtkTreeSelection *tree_sel = NULL;
+ gint tree_sel_card = 0;
+
+ GcmdGtkFoldview::View::ctx_menu_data *ctxdata = NULL;
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // get path to iter over which the user clicked
+ gtk_tree_view_get_path_at_pos(
+ GTK_TREE_VIEW(tree_view),
+ (gint) event->x,
+ (gint) event->y,
+ &path_clicked, NULL, NULL, NULL);
+
+ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ // get path to currently selected iter
+ tree_sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view));
+ if ( ! tree_sel )
+ {
+ gwr_err("View::signal_button_press_event:gtk_tree_view_get_selection failed");
+ return FALSE;
+ }
+
+ // Note: gtk_tree_selection_count_selected_rows() does not
+ // exist in gtk+-2.0, only in gtk+ >= v2.2 !
+ tree_sel_card = gtk_tree_selection_count_selected_rows(tree_sel);
+
+ if ( tree_sel_card == 1 )
+ {
+ if ( gtk_tree_selection_get_selected( tree_sel, NULL, &iter_selected) )
+ {
+ path_selected = gtk_tree_model_get_path(
+ gtk_tree_view_get_model(GTK_TREE_VIEW(tree_view)),
+ &iter_selected);
+
+ if ( !path_selected )
+ {
+ gwr_wng("View::signal_button_press_event:gtk_tree_model_get_path failed");
+ }
+ }
+ else
+ {
+ gwr_wng("View::signal_button_press_event:gtk_tree_selection_get_selected failed");
+ return FALSE;
+ }
+ }
+
+ //.........................................................................
+ // single left click
+ if ( ( event->type == GDK_BUTTON_PRESS ) && ( event->button == 1 ) )
+ {
+ // The GtkTreeSelection will be updated only
+ // in the next loop of gtk_main(), and when calling sync(),
+ // the path_selected is still the old selected item, not the
+ // clicked one.
+
+ // So in the sync() function, we use path_clicked instead of
+ // path_selected
+
+ // And this doesnt work - next gtk_main loop too
+ //gtk_tree_selection_unselect_all(tree_sel);
+ //gtk_tree_selection_select_path(tree_sel, path_clicked);
+
+ ctxdata = new GcmdGtkFoldview::View::ctx_menu_data();
+ ctxdata->a_foldview = (GcmdGtkFoldview*)data;
+ ctxdata->a_time = event->time;
+ ctxdata->a_event_x = event->x;
+ ctxdata->a_event_y = event->y;
+ ctxdata->a_button = event->button;
+ ctxdata->d_path_selected = path_selected;
+ ctxdata->d_path_clicked = path_clicked;
+
+ return ((GcmdGtkFoldview*)data)->view.click_left_single(ctxdata);
+ }
+
+ //.........................................................................
+ // single right click : ctx menu
+ if ( ( event->type == GDK_BUTTON_PRESS ) && ( event->button == 3 ) )
+ {
+ ctxdata = new GcmdGtkFoldview::View::ctx_menu_data();
+ ctxdata->a_foldview = (GcmdGtkFoldview*)data;
+ ctxdata->a_time = event->time;
+ ctxdata->a_event_x = event->x;
+ ctxdata->a_event_y = event->y;
+ ctxdata->a_button = event->button;
+ ctxdata->d_path_selected = path_selected;
+ ctxdata->d_path_clicked = path_clicked;
+
+ return ((GcmdGtkFoldview*)data)->view.context_menu_pop(ctxdata);
+ }
+
+ //.........................................................................
+ // double left click
+ if ( ( event->type == GDK_2BUTTON_PRESS ) && ( event->button == 1 ) )
+ {
+ ctxdata = new GcmdGtkFoldview::View::ctx_menu_data();
+ ctxdata->a_foldview = (GcmdGtkFoldview*)data;
+ ctxdata->a_time = event->time;
+ ctxdata->a_event_x = event->x;
+ ctxdata->a_event_y = event->y;
+ ctxdata->a_button = event->button;
+ ctxdata->d_path_selected = path_selected;
+ ctxdata->d_path_clicked = path_clicked;
+
+ return ((GcmdGtkFoldview*)data)->view.click_left_double(ctxdata);
+ }
+
+ // signal was not handled
+ return FALSE;
+}
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Drag n Drop
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+void GcmdGtkFoldview::View::signal_drag_begin(
+ GtkWidget *widget,
+ GdkDragContext *drag_context,
+ gpointer user_data)
+{
+ gwr_inf("View:signal_drag_begin");
+}
+
+//=============================================================================
+// Contextual menu
+//=============================================================================
+gboolean GcmdGtkFoldview::View::context_menu_pop(ctx_menu_data *ctxdata)
+{
+ s_context_menu.a_widget = gtk_menu_new();
+
+ if ( ctxdata->d_path_selected )
+ {
+ if ( ctxdata->d_path_clicked )
+ {
+ if ( gtk_tree_path_compare(
+ ctxdata->d_path_clicked,
+ ctxdata->d_path_selected) == 0 )
+ {
+ ctxdata->a_foldview->control_context_menu_populate_add_section (s_context_menu.a_widget, 0, ctxdata);
+ ctxdata->a_foldview->control_context_menu_populate_add_separator(s_context_menu.a_widget);
+ ctxdata->a_foldview->control_context_menu_populate_add_section (s_context_menu.a_widget, 1, ctxdata);
+ }
+ else
+ {
+ ctxdata->a_foldview->control_context_menu_populate_add_section(s_context_menu.a_widget, 1, ctxdata);
+ }
+ }
+ else
+ {
+ ctxdata->a_foldview->control_context_menu_populate_add_section (s_context_menu.a_widget, 0, ctxdata);
+ ctxdata->a_foldview->control_context_menu_populate_add_separator(s_context_menu.a_widget);
+ ctxdata->a_foldview->control_context_menu_populate_add_section (s_context_menu.a_widget, 1, ctxdata);
+ }
+ }
+ else
+ {
+ ctxdata->a_foldview->control_context_menu_populate_add_section(s_context_menu.a_widget, 1, ctxdata);
+ }
+
+ gtk_widget_show_all(s_context_menu.a_widget);
+
+ // pop
+ // void gtk_menu_popup(
+ // GtkMenu *menu,
+ // GtkWidget *parent_menu_shell,
+ // GtkWidget *parent_menu_item,
+ // GtkMenuPositionFunc func,
+ // gpointer data,
+ // guint button,
+ // guint32 activate_time);
+ //
+ // menu : a GtkMenu.
+ // parent_menu_shell : the menu shell containing the triggering menu item, or NULL. [allow-none]
+ // parent_menu_item : the menu item whose activation triggered the popup, or NULL. [allow-none]
+ // func : a user supplied function used to position the menu, or NULL. [allow-none]
+ // data : user supplied data to be passed to func. [allow-none]
+ // button : the mouse button which was pressed to initiate the event.
+ // activate_time : the time at which the activation event occurred.
+ gtk_menu_popup(
+ GTK_MENU(s_context_menu.a_widget), NULL, NULL,
+ NULL, NULL,
+ ctxdata->a_button, ctxdata->a_time);
+
+ return TRUE;
+}
+
+//=============================================================================
+// Selection
+//=============================================================================
+gboolean GcmdGtkFoldview::View::click_left_single(ctx_menu_data *ctxdata)
+{
+ // simulate a callback, avoiding accessing to GcmdGtkFoldview singleton
+ GcmdGtkFoldview::Control_sync_update(NULL, ctxdata);
+
+ // tell gtk to continue signal treatment, else treeview wont
+ // expand / collapse anymore if that was the arrow that was clicked
+ return FALSE;
+}
+
+//=============================================================================
+// Contextual menu
+//=============================================================================
+gboolean GcmdGtkFoldview::View::click_left_double(ctx_menu_data *ctxdata)
+{
+ // simulate a callback, avoiding accessing to GcmdGtkFoldview singleton
+ GcmdGtkFoldview::Control_set_active_tab(NULL, ctxdata);
+
+ return TRUE;
+}
+
+//=============================================================================
+// composite widget con_combo
+//=============================================================================
+void GcmdGtkFoldview::View::connection_combo_add_connection(GnomeCmdCon *con)
+{
+ GnomeCmdCombo *combo = GNOME_CMD_COMBO(connection_combo());
+ gchar *text[3];
+
+ text[0] = NULL;
+ text[1] = (gchar *)gnome_cmd_con_get_alias(con);
+ text[2] = NULL;
+
+ GnomeCmdPixmap *pixmap = gnome_cmd_con_get_go_pixmap (con);
+ if (pixmap)
+ {
+ gint row = combo->append(text, con);
+ combo->set_pixmap(row, 0, pixmap);
+ }
+}
+
+void GcmdGtkFoldview::View::connection_combo_reset()
+{
+ GnomeCmdCombo *combo = GNOME_CMD_COMBO(m_con_combo);
+
+ combo->clear();
+ combo->highest_pixmap = 20;
+ combo->widest_pixmap = 20;
+ gtk_clist_set_row_height (GTK_CLIST (combo->list), 20);
+ gtk_clist_set_column_width (GTK_CLIST (combo->list), 0, 20);
+}
+
+//=============================================================================
+// Theming
+//=============================================================================
+void GcmdGtkFoldview::View::update_style()
+{
+ gtk_widget_set_style (GTK_WIDGET(treeview()), style_foldview);
+ ((GnomeCmdCombo*)connection_combo())->update_style();
+}
diff --git a/src/gnome-cmd-foldview.cc b/src/gnome-cmd-foldview.cc
new file mode 100644
index 0000000..a950a97
--- /dev/null
+++ b/src/gnome-cmd-foldview.cc
@@ -0,0 +1,380 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ ---------------------------------------------------------------------------
+
+ C++
+
+ Contains variadic macros
+
+ ---------------------------------------------------------------------------
+
+ 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 option) 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#include <config.h>
+
+#include <stdlib.h>
+
+#include <gtk/gtksignal.h>
+#include <gtk/gtkvbox.h>
+
+#include <libgnomevfs/gnome-vfs.h>
+#include <libgnomevfs/gnome-vfs-utils.h>
+
+#include "gnome-cmd-includes.h"
+#include "gnome-cmd-combo.h"
+#include "gnome-cmd-main-win.h"
+#include "gnome-cmd-style.h"
+#include "gnome-cmd-data.h"
+
+#include "gnome-cmd-foldview-private.h"
+#include "gnome-cmd-foldview-gvfs.h"
+
+// ***************************************************************************
+// * *
+// * Defines *
+// * *
+// ***************************************************************************
+
+#define GVFS_MAX_ASYNC_OPS 10000
+#define GVFS_ITEMS_PER_NOTIFICATION 30
+
+// ***************************************************************************
+// * *
+// * Helpers *
+// * *
+// ***************************************************************************
+
+//=============================================================================
+// Common vars
+//=============================================================================
+static GnomeVFSResult sVFSResult = GNOME_VFS_OK; // for sync operations
+
+extern GnomeCmdMainWin *main_win;
+
+//=============================================================================
+// Logger
+//=============================================================================
+/*
+ <ESC>[{attr};{fg};{bg}m
+
+{attr} needs to be one of the following:
+ 0 Reset All Attributes (return to normal mode)
+ 1 Bright (usually turns on BOLD)
+ 2 Dim
+ 3 Underline
+ 5 Blink
+ 7 Reverse
+ 8 Hidden
+
+{fg} needs to be one of the following:
+ 30 Black
+ 31 Red
+ 32 Green
+ 33 Yellow
+ 34 Blue
+ 35 Magenta
+ 36 Cyan
+ 37 White
+
+{bg} needs to be one of the following:
+ 40 Black
+ 41 Red
+ 42 Green
+ 43 Yellow
+ 44 Blue
+ 45 Magenta
+ 46 Cyan
+ 47 White
+*/
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Core logging
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+static char sLogStr [1024];
+static char sLogStrFinal[1024];
+
+void gwr_print(const char* str)
+{
+ sprintf(sLogStrFinal,"%s%s", str,sLogStr);
+ printf("%s\n",sLogStrFinal);
+}
+void gwr_inf(const char* fmt, ...)
+{
+ #ifndef DEBUG_SHOW_INF
+ return;
+ #endif
+ va_list val; va_start(val, fmt); vsprintf(sLogStr, fmt, val); va_end(val);
+ gwr_print("\033[0;32mINF:\033[0;30m");
+}
+void gwr_wng(const char* fmt, ...)
+{
+ #ifndef DEBUG_SHOW_WNG
+ return;
+ #endif
+ va_list val; va_start(val, fmt); vsprintf(sLogStr, fmt, val); va_end(val);
+ gwr_print("\033[0;35mWNG:\033[0;30m");
+}
+void gwr_err(const char* fmt, ...)
+{
+ #ifndef DEBUG_SHOW_ERR
+ return;
+ #endif
+ va_list val; va_start(val, fmt); vsprintf(sLogStr, fmt, val); va_end(val);
+ gwr_print("\033[0;31mERR:\033[0;30m");
+}
+void gwr_inf_vfs(const char* fmt, ...)
+{
+ #ifndef DEBUG_SHOW_VFS
+ return;
+ #endif
+ va_list val; va_start(val, fmt); vsprintf(sLogStr, fmt, val); va_end(val);
+ strcat(sLogStr, " [VFS-INF:");
+ strcat(sLogStr, gnome_vfs_result_to_string(sVFSResult));
+ strcat(sLogStr, "]");
+ gwr_print("\033[0;31mERR:\033[0;30m");
+}
+void gwr_err_vfs(const char* fmt, ...)
+{
+ #ifndef DEBUG_SHOW_VFS
+ return;
+ #endif
+ va_list val; va_start(val, fmt); vsprintf(sLogStr, fmt, val); va_end(val);
+ strcat(sLogStr, " [VFS-ERR:");
+ strcat(sLogStr, gnome_vfs_result_to_string(sVFSResult));
+ strcat(sLogStr, "]");
+ gwr_print("\033[0;31mERR:\033[0;30m");
+}
+
+
+// ***************************************************************************
+// * *
+// * Divers *
+// * *
+// ***************************************************************************
+GcmdGtkFoldview::eFileAccess GcmdGtkFoldview::Access_from_permissions(
+ GnomeVFSFilePermissions permissions)
+{
+ eFileAccess access = eAccessUnknown;
+ gboolean b_read = FALSE;
+ gboolean b_write = FALSE;
+ if ( ( permissions & GNOME_VFS_PERM_ACCESS_READABLE ) != 0 ) b_read = TRUE;
+ if ( ( permissions & GNOME_VFS_PERM_ACCESS_WRITABLE ) != 0 ) b_write = TRUE;
+ if ( b_read )
+ {
+ access = ( b_write ? eAccessReadWrite : eAccessReadOnly );
+ }
+ else
+ {
+ access = ( b_write ? eAccessUnknown : eAccessForbidden );
+ }
+ return access;
+}
+
+GcmdGtkFoldview::View::eIcon GcmdGtkFoldview::View::Icon_from_type_permissions(
+ GnomeVFSFileType type,
+ GnomeVFSFilePermissions permissions)
+{
+ eFileAccess access = eAccessUnknown;
+
+ access = Access_from_permissions(permissions);
+
+ return Icon_from_type_access(type, access);
+}
+
+GcmdGtkFoldview::View::eIcon GcmdGtkFoldview::View::Icon_from_type_access(
+ GnomeVFSFileType type,
+ GcmdGtkFoldview::eFileAccess access)
+{
+ if ( type == GNOME_VFS_FILE_TYPE_DIRECTORY )
+ {
+ switch ( access )
+ {
+ case eAccessReadWrite: return GcmdGtkFoldview::View::eIconDirReadWrite; break;
+ case eAccessReadOnly : return GcmdGtkFoldview::View::eIconDirReadOnly; break;
+ case eAccessForbidden: return GcmdGtkFoldview::View::eIconDirForbidden; break;
+ default : return GcmdGtkFoldview::View::eIconUnknown; break;
+ }
+ }
+
+ if ( type == GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK )
+ {
+ switch ( access )
+ {
+ case eAccessReadWrite: return GcmdGtkFoldview::View::eIconSymlinkToDirReadWrite; break;
+ case eAccessReadOnly : return GcmdGtkFoldview::View::eIconSymlinkToDirReadOnly; break;
+ case eAccessForbidden: return GcmdGtkFoldview::View::eIconSymlinkToDirForbidden; break;
+ default : return GcmdGtkFoldview::View::eIconUnknown; break;
+ }
+ }
+
+ return View::eIconUnknown;
+}
+
+// ***************************************************************************
+// * *
+// * widget showing / hiding *
+// * *
+// ***************************************************************************
+static GtkWidget* GcmdGtkFoldviewSingleton = NULL;
+
+// ***************************************************************************
+// * *
+// * public interface *
+// * *
+// ***************************************************************************
+
+//=============================================================================
+// Singleton
+//=============================================================================
+
+GtkWidget* GcmdWidget()
+{
+ if ( GcmdGtkFoldviewSingleton != NULL )
+ return GcmdGtkFoldviewSingleton;
+
+ GcmdGtkFoldviewSingleton = gcmdgtkfoldview_new();
+
+ return GcmdGtkFoldviewSingleton;
+}
+
+GcmdGtkFoldview* GcmdFoldview()
+{
+ return (GcmdGtkFoldview*)( GcmdWidget() );
+}
+
+void gnome_cmd_foldview_update_style(GtkWidget *widget)
+{
+ g_return_if_fail( widget != NULL );
+
+ (GCMDGTKFOLDVIEW(widget))->view.update_style();
+}
+
+GtkWidget* gnome_cmd_foldview_get_instance()
+{
+ return GcmdWidget();
+}
+
+//=============================================================================
+// Init
+//=============================================================================
+
+//=============================================================================
+// Root element
+//=============================================================================
+gboolean GcmdGtkFoldview::root_uri_set_1(gchar * text)
+{
+ GnomeVFSURI *uri = GVFS_uri_new(text);
+ control_root_uri_set(uri);
+ gnome_vfs_uri_unref(uri);
+ return TRUE;
+}
+
+gboolean GcmdGtkFoldview::root_uri_set_2(GnomeVFSURI *uri)
+{
+ return control_root_uri_set(uri);
+}
+
+
+
+// ***************************************************************************
+// * *
+// * gtk implementation *
+// * *
+// ***************************************************************************
+
+enum
+{
+ GCMDGTKFOLDVIEW_SIGNAL,
+ LAST_SIGNAL
+};
+
+static void gcmdgtkfoldview_class_init (GcmdGtkFoldviewClass *klass);
+static void gcmdgtkfoldview_init (GcmdGtkFoldview *ttt);
+//static void init (GcmdGtkFoldview *foldview);
+
+static guint gcmdgtkfoldview_signals[LAST_SIGNAL] = { 0 };
+
+
+
+//-----------------------------------------------------------------------------
+// GcmdGtkFoldview GType implementation
+//-----------------------------------------------------------------------------
+GType
+gcmdgtkfoldview_get_type (void)
+{
+ static GType fv_type = 0;
+
+ if (!fv_type)
+ {
+ const GTypeInfo fv_info =
+ {
+ sizeof (GcmdGtkFoldviewClass),
+ NULL, /* base_init */
+ NULL, /* base_finalize */
+ (GClassInitFunc) gcmdgtkfoldview_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (GcmdGtkFoldview),
+ 0,
+ (GInstanceInitFunc) gcmdgtkfoldview_init,
+ };
+
+ fv_type = g_type_register_static(GTK_TYPE_VBOX, "gtkGcmdFoldview", &fv_info, (GTypeFlags)0);
+ }
+
+ return fv_type;
+}
+
+//-----------------------------------------------------------------------------
+// GcmdGtkFoldview class initialization
+//-----------------------------------------------------------------------------
+static void
+gcmdgtkfoldview_class_init (GcmdGtkFoldviewClass *klass)
+{
+ gcmdgtkfoldview_signals[GCMDGTKFOLDVIEW_SIGNAL] = g_signal_new(
+ "gcmdgtkfoldview",
+ G_TYPE_FROM_CLASS (klass),
+ (GSignalFlags)(G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
+ G_STRUCT_OFFSET (GcmdGtkFoldviewClass, gcmdgtkfoldview),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+//-----------------------------------------------------------------------------
+// GcmdGtkFoldview instance initialization
+//-----------------------------------------------------------------------------
+static void
+gcmdgtkfoldview_init (GcmdGtkFoldview *foldview)
+{
+ foldview->control_init_instance();
+}
+
+GtkWidget*
+gcmdgtkfoldview_new ()
+{
+ return GTK_WIDGET (g_object_new (GCMDGTKFOLDVIEW_TYPE, NULL));
+}
+
+void
+gcmdgtkfoldview_clear (GcmdGtkFoldview *foldview)
+{
+}
diff --git a/src/gnome-cmd-foldview.h b/src/gnome-cmd-foldview.h
new file mode 100644
index 0000000..f9464b4
--- /dev/null
+++ b/src/gnome-cmd-foldview.h
@@ -0,0 +1,40 @@
+/*
+ GNOME Commander - A GNOME based file manager
+ Copyright (C) 2001-2006 Marcus Bjurman
+ Copyright (C) 2007-2010 Piotr Eljasiak
+ Copyright (C) 2010-2010 Guillaume Wardavoir
+
+ 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 option) 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 St, Fifth Floor, Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GCMDGTKFOLDVIEW_H__
+#define __GCMDGTKFOLDVIEW_H__
+
+//=============================================================================
+//
+// public header file
+//
+//=============================================================================
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtklabel.h>
+
+// This function because of the creation process of GtkWidgets. Annoying.
+GtkWidget* gnome_cmd_foldview_get_instance();
+void gnome_cmd_foldview_update_style (GtkWidget *widget);
+
+#endif //__GCMDGTKFOLDVIEW_H__
diff --git a/src/gnome-cmd-main-menu.cc b/src/gnome-cmd-main-menu.cc
index 256525d..54475ac 100644
--- a/src/gnome-cmd-main-menu.cc
+++ b/src/gnome-cmd-main-menu.cc
@@ -660,6 +660,12 @@ static void init (GnomeCmdMainMenu *main_menu)
GNOME_APP_PIXMAP_NONE, NULL,
NULL
},
+ {
+ MENU_TYPE_TOGGLEITEM, _("Show Treeview"), "", NULL,
+ (gpointer) view_treeview, NULL,
+ GNOME_APP_PIXMAP_NONE, NULL,
+ NULL
+ },
MENUTYPE_SEPARATOR,
{
MENU_TYPE_TOGGLEITEM, _("Show Hidden Files"), "", NULL,
@@ -848,8 +854,9 @@ static void init (GnomeCmdMainMenu *main_menu)
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_menu_uiinfo[10].widget), gnome_cmd_data.concombo_visibility);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_menu_uiinfo[11].widget), gnome_cmd_data.cmdline_visibility);
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_menu_uiinfo[12].widget), gnome_cmd_data.buttonbar_visibility);
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_menu_uiinfo[14].widget), !gnome_cmd_data.filter_settings.hidden);
- gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_menu_uiinfo[15].widget), !gnome_cmd_data.filter_settings.backup);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_menu_uiinfo[13].widget), FALSE);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_menu_uiinfo[15].widget), !gnome_cmd_data.filter_settings.hidden);
+ gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (view_menu_uiinfo[16].widget), !gnome_cmd_data.filter_settings.backup);
g_signal_connect (gnome_cmd_con_list_get (), "list-changed", G_CALLBACK (on_con_list_list_changed), main_menu);
diff --git a/src/gnome-cmd-main-win.cc b/src/gnome-cmd-main-win.cc
index 3c10f1b..92989c0 100644
--- a/src/gnome-cmd-main-win.cc
+++ b/src/gnome-cmd-main-win.cc
@@ -38,6 +38,7 @@
#include "gnome-cmd-plain-path.h"
#include "gnome-cmd-con.h"
#include "gnome-cmd-con-list.h"
+#include "gnome-cmd-foldview.h"
#include "owner.h"
#include "utils.h"
#include "dialogs/gnome-cmd-manage-bookmarks-dialog.h"
@@ -89,6 +90,8 @@ struct GnomeCmdMainWin::Private
GtkWidget *main_win;
GtkWidget *vbox;
+ GtkWidget *foldview_paned;
+ GtkWidget *foldview;
GtkWidget *paned;
GtkWidget *file_selector[2];
GtkWidget *focused_widget;
@@ -784,6 +787,10 @@ static void init (GnomeCmdMainWin *mw)
gnome_app_set_contents (GNOME_APP (mw), mw->priv->vbox);
+ mw->priv->foldview = NULL;
+ mw->priv->foldview_paned = NULL; // gcmd-foldview is not yet in metadata
+
+
mw->priv->paned = gnome_cmd_data.list_orientation ? gtk_vpaned_new () : gtk_hpaned_new ();
g_object_ref (mw->priv->paned);
@@ -931,6 +938,8 @@ void GnomeCmdMainWin::update_style()
if (gnome_cmd_data.cmdline_visibility)
gnome_cmd_cmdline_update_style (GNOME_CMD_CMDLINE (priv->cmdline));
+
+ gnome_cmd_foldview_update_style (priv->foldview);
}
@@ -1162,6 +1171,18 @@ static void gnome_cmd_main_win_real_switch_fs (GnomeCmdMainWin *mw, GnomeCmdFile
}
+GtkWidget *GnomeCmdMainWin::get_vbox() const
+{
+ return priv->vbox;
+}
+
+
+GtkWidget *GnomeCmdMainWin::get_paned() const
+{
+ return priv->paned;
+}
+
+
GnomeCmdCmdline *GnomeCmdMainWin::get_cmdline() const
{
return GNOME_CMD_CMDLINE (priv->cmdline);
@@ -1242,6 +1263,65 @@ void GnomeCmdMainWin::update_buttonbar_visibility()
}
+void GnomeCmdMainWin::update_treeview_visibility(gboolean visible)
+{
+ guint length = 0;
+ gint pos = 0;
+
+ // Ensure object is created before calling show / hide, coz I have
+ // signals in widget creation, leading to... a bug
+ if (!priv->foldview)
+ priv->foldview = gnome_cmd_foldview_get_instance();
+
+ if (visible)
+ {
+ // style
+ gnome_cmd_foldview_update_style (priv->foldview);
+
+ priv->foldview_paned = gtk_hpaned_new ();
+
+ g_object_ref (priv->paned);
+ gtk_container_remove (GTK_CONTAINER (priv->vbox), priv->paned);
+ gtk_paned_pack1 (GTK_PANED (priv->foldview_paned), priv->foldview, FALSE, TRUE);
+ gtk_paned_pack2 (GTK_PANED (priv->foldview_paned), priv->paned, FALSE, TRUE);
+ g_object_unref (priv->paned);
+
+ gtk_box_pack_start (GTK_BOX (priv->vbox), priv->foldview_paned, TRUE, TRUE, 0);
+
+ // put the foldview_paned at its right place
+ // rule : there are only cmdline & buttons after us
+ length = g_list_length (gtk_container_get_children (GTK_CONTAINER (priv->vbox)));
+ pos = length - 1;
+ if (priv->buttonbar) pos -= 2;
+ if (priv->cmdline) pos -= 2;
+ gtk_box_reorder_child (GTK_BOX (priv->vbox), priv->foldview_paned, pos);
+
+ // show
+ gtk_widget_show_all (priv->foldview_paned);
+ }
+ else
+ {
+ g_object_ref (priv->paned);
+ gtk_container_remove (GTK_CONTAINER (priv->foldview_paned), priv->foldview);
+ gtk_container_remove (GTK_CONTAINER (priv->foldview_paned), priv->paned);
+ gtk_container_remove (GTK_CONTAINER (priv->vbox), priv->foldview_paned);
+ gtk_box_pack_start (GTK_BOX (priv->vbox), priv->paned, TRUE, TRUE, 0);
+ g_object_unref (priv->paned);
+
+ priv->foldview = NULL;
+ priv->foldview_paned = NULL;
+
+ // put the gcmd paned at its right place
+ // rule : there are only cmdline & buttons after us
+ length = g_list_length (gtk_container_get_children (GTK_CONTAINER (priv->vbox)));
+ pos = length - 1;
+ if (priv->buttonbar) pos -= 2;
+ if (priv->cmdline) pos -= 2;
+ gtk_box_reorder_child (GTK_BOX (priv->vbox), priv->paned, pos);
+ }
+}
+
+
void GnomeCmdMainWin::update_cmdline_visibility()
{
if (gnome_cmd_data.cmdline_visibility)
@@ -1277,10 +1357,14 @@ void GnomeCmdMainWin::update_list_orientation()
g_object_ref (priv->file_selector[LEFT]);
g_object_ref (priv->file_selector[RIGHT]);
+
gtk_container_remove (GTK_CONTAINER (priv->paned), priv->file_selector[LEFT]);
gtk_container_remove (GTK_CONTAINER (priv->paned), priv->file_selector[RIGHT]);
- gtk_object_destroy (GTK_OBJECT (priv->paned));
+ if (priv->foldview)
+ gtk_container_remove (GTK_CONTAINER (priv->foldview_paned), priv->paned);
+
+ g_object_unref (priv->paned);
priv->paned = gnome_cmd_data.list_orientation ? gtk_vpaned_new () : gtk_hpaned_new ();
@@ -1291,11 +1375,16 @@ void GnomeCmdMainWin::update_list_orientation()
gtk_paned_pack1 (GTK_PANED (priv->paned), priv->file_selector[LEFT], TRUE, TRUE);
gtk_paned_pack2 (GTK_PANED (priv->paned), priv->file_selector[RIGHT], TRUE, TRUE);
- if (gnome_cmd_data.toolbar_visibility)
- pos += 2;
+ if (priv->foldview)
+ gtk_paned_pack2 (GTK_PANED (priv->foldview_paned), priv->paned, FALSE, TRUE);
+ else
+ {
+ if (gnome_cmd_data.toolbar_visibility)
+ pos += 2;
- gtk_box_pack_start (GTK_BOX (priv->vbox), priv->paned, TRUE, TRUE, 0);
- gtk_box_reorder_child (GTK_BOX (priv->vbox), priv->paned, pos);
+ gtk_box_pack_start (GTK_BOX (priv->vbox), priv->paned, TRUE, TRUE, 0);
+ gtk_box_reorder_child (GTK_BOX (priv->vbox), priv->paned, pos);
+ }
g_object_unref (priv->file_selector[LEFT]);
g_object_unref (priv->file_selector[RIGHT]);
diff --git a/src/gnome-cmd-main-win.h b/src/gnome-cmd-main-win.h
index d330a40..9024f5a 100644
--- a/src/gnome-cmd-main-win.h
+++ b/src/gnome-cmd-main-win.h
@@ -75,6 +75,8 @@ struct GnomeCmdMainWin
GnomeCmdState *get_state() const;
void set_cap_state(gboolean state);
+ GtkWidget *get_vbox() const;
+ GtkWidget *get_paned() const;
GnomeCmdCmdline *get_cmdline() const;
void focus_file_lists();
@@ -83,6 +85,7 @@ struct GnomeCmdMainWin
void update_style();
void update_bookmarks();
void update_toolbar_visibility();
+ void update_treeview_visibility(gboolean visible);
void update_cmdline_visibility();
void update_buttonbar_visibility();
void update_list_orientation();
diff --git a/src/gnome-cmd-style.cc b/src/gnome-cmd-style.cc
index 2697362..6e08e59 100644
--- a/src/gnome-cmd-style.cc
+++ b/src/gnome-cmd-style.cc
@@ -33,6 +33,8 @@ GtkStyle *alt_list_style = NULL;
GtkStyle *sel_list_style = NULL;
GtkStyle *alt_sel_list_style = NULL;
+GtkStyle *style_foldview = NULL;
+GtkStyle *style_foldview_selected = NULL;
inline GtkStyle *create_list_style ()
{
@@ -169,6 +171,82 @@ inline GtkStyle *create_alt_sel_list_style ()
}
+inline GtkStyle *create_style_foldview()
+{
+ GnomeCmdColorTheme *cols = gnome_cmd_data_get_current_color_theme ();
+ const gchar *font_name = gnome_cmd_data_get_list_font ();
+ GtkStyle *style = gtk_style_new ();
+
+ // set style font to default font
+ if (strcmp (font_name, "default") != 0)
+ {
+ PangoFontDescription *pfont = pango_font_description_from_string (font_name);
+
+ if (pfont && pango_font_description_get_size (pfont) != 0)
+ {
+ if (style->font_desc)
+ pango_font_description_free (style->font_desc);
+ style->font_desc = pfont;
+ }
+ }
+
+ if (!cols->respect_theme)
+ {
+ // Warning modify this leads to madness
+ style->base[GTK_STATE_NORMAL] = *cols->norm_bg;
+ style->base[GTK_STATE_ACTIVE] = *cols->curs_bg;
+ style->base[GTK_STATE_SELECTED] = *cols->curs_bg;
+
+ style->fg[GTK_STATE_NORMAL] = *cols->norm_fg;
+ style->fg[GTK_STATE_SELECTED] = *cols->norm_fg;
+
+ style->bg[GTK_STATE_NORMAL] = *cols->norm_bg;
+ style->bg[GTK_STATE_SELECTED] = *cols->curs_bg;
+
+ style->text[GTK_STATE_NORMAL] = *cols->norm_fg;
+ }
+
+ return style;
+}
+
+
+inline GtkStyle *create_style_foldview_selected()
+{
+ GnomeCmdColorTheme *cols = gnome_cmd_data_get_current_color_theme ();
+ const gchar *font_name = gnome_cmd_data_get_list_font ();
+ GtkStyle *style = gtk_style_new ();
+
+ // set style font to default font
+ if (strcmp (font_name, "default") != 0)
+ {
+ PangoFontDescription *pfont = pango_font_description_from_string (font_name);
+
+ if (pfont && pango_font_description_get_size (pfont) != 0)
+ {
+ if (style->font_desc)
+ pango_font_description_free (style->font_desc);
+ style->font_desc = pfont;
+ }
+ }
+
+ if (!cols->respect_theme)
+ {
+ style->base[GTK_STATE_NORMAL] = *cols->norm_bg;
+ style->bg[GTK_STATE_NORMAL] = *cols->sel_bg;
+ style->fg[GTK_STATE_NORMAL] = *cols->sel_fg;
+
+ style->base[GTK_STATE_ACTIVE] = *cols->norm_bg;
+
+ style->fg[GTK_STATE_SELECTED] = *cols->sel_fg;
+ style->bg[GTK_STATE_SELECTED] = *cols->curs_bg;
+
+ style->text[GTK_STATE_NORMAL] = *cols->sel_fg;
+ }
+
+ return style;
+}
+
+
void gnome_cmd_style_create ()
{
if (list_style) g_object_unref (list_style);
@@ -176,8 +254,16 @@ void gnome_cmd_style_create ()
if (sel_list_style) g_object_unref (sel_list_style);
if (alt_sel_list_style) g_object_unref (alt_sel_list_style);
+ if (style_foldview)
+ g_object_unref (style_foldview);
+ if (style_foldview_selected)
+ g_object_unref (style_foldview_selected);
+
list_style = create_list_style ();
alt_list_style = create_alt_list_style ();
sel_list_style = create_sel_list_style ();
alt_sel_list_style = create_alt_sel_list_style ();
+
+ style_foldview = create_style_foldview();
+ style_foldview_selected = create_style_foldview_selected();
}
diff --git a/src/gnome-cmd-style.h b/src/gnome-cmd-style.h
index 0e728a9..75ebf76 100644
--- a/src/gnome-cmd-style.h
+++ b/src/gnome-cmd-style.h
@@ -24,6 +24,8 @@
extern GtkStyle *list_style, *sel_list_style;
extern GtkStyle *alt_list_style, *alt_sel_list_style;
+extern GtkStyle *style_foldview, *style_foldview_selected;
+
void gnome_cmd_style_create ();
#endif // __GNOME_CMD_STYLE_H__
diff --git a/src/gnome-cmd-user-actions.cc b/src/gnome-cmd-user-actions.cc
index 22b51d8..b700763 100644
--- a/src/gnome-cmd-user-actions.cc
+++ b/src/gnome-cmd-user-actions.cc
@@ -1337,6 +1337,16 @@ void view_buttonbar (GtkMenuItem *menuitem, gpointer not_used)
}
+void view_treeview (GtkMenuItem *menuitem, gpointer not_used)
+{
+ if (!GTK_WIDGET_REALIZED (main_win)) return;
+
+ GtkCheckMenuItem *checkitem = (GtkCheckMenuItem *) menuitem;
+ // gnome_cmd_data.treeview_visibility = checkitem->active;
+ main_win->update_treeview_visibility(checkitem->active);
+}
+
+
void view_cmdline (GtkMenuItem *menuitem, gpointer not_used)
{
if (!GTK_WIDGET_REALIZED (main_win)) return;
diff --git a/src/gnome-cmd-user-actions.h b/src/gnome-cmd-user-actions.h
index 7187d76..d3d7e63 100644
--- a/src/gnome-cmd-user-actions.h
+++ b/src/gnome-cmd-user-actions.h
@@ -278,6 +278,7 @@ GNOME_CMD_USER_ACTION(view_conbuttons);
GNOME_CMD_USER_ACTION(view_concombo);
GNOME_CMD_USER_ACTION(view_toolbar);
GNOME_CMD_USER_ACTION(view_buttonbar);
+GNOME_CMD_USER_ACTION(view_treeview);
GNOME_CMD_USER_ACTION(view_cmdline);
GNOME_CMD_USER_ACTION(view_hidden_files);
GNOME_CMD_USER_ACTION(view_backup_files);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]